├── .coveralls.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── controllers │ └── ldap_settings_controller.rb ├── helpers │ └── ldap_settings_helper.rb ├── models │ ├── ldap_setting.rb │ └── ldap_test.rb └── views │ └── ldap_settings │ ├── _ldap_settings.html.erb │ ├── _synchronization_actions.html.erb │ ├── _test.html.erb │ ├── base_settings.js.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── ldap_setting_invalid.text.erb │ ├── ldap_test_invalid.text.erb │ └── test.text.erb ├── assets ├── images │ ├── disable.png │ ├── enable.png │ └── server_key.png ├── javascripts │ └── ldap_settings.js └── stylesheets │ └── ldap_sync.css ├── config ├── Gemfile.travis ├── base_settings.yml ├── database.yml.travis ├── locales │ ├── de.yml │ ├── en.yml │ ├── es.yml │ ├── fr.yml │ ├── ja.yml │ ├── nl.yml │ ├── pl.yml │ ├── pt.yml │ └── ru.yml └── routes.rb ├── db └── migrate │ ├── 201108021245_change_settings_name.rb │ ├── 201110050735_add_user_memberid_setting.rb │ ├── 201111271700_add_group_membership_setting.rb │ ├── 201201010043_create_ldap_cache_dir.rb │ ├── 201201071359_update_attributes_to_sync.rb │ ├── 201201291950_rename_must_be_member_of_and_add_to_group_settings.rb │ ├── 201201302250_remove_attr_prefix_settings.rb │ ├── 201202082153_add_account_flags_setting.rb │ ├── 201211202050_update_check_box_values.rb │ ├── 201302052050_update_user_group_fields.rb │ ├── 201302202301_change_setting_id_from_name_to_auth_source_id.rb │ ├── 201302212308_enable_sync_on_login.rb │ ├── 201503252355_add_users_search_scope.rb │ └── 20170524063056_rename_account_disabled_test.rb ├── doc └── RUNNING_TESTS ├── init.rb ├── lib ├── ldap_sync │ ├── core_ext.rb │ ├── core_ext │ │ ├── ber.rb │ │ ├── file_store.rb │ │ ├── ldap.rb │ │ ├── ldap_entry.rb │ │ ├── migration.rb │ │ └── string.rb │ ├── dry_run │ │ ├── group.rb │ │ └── user.rb │ ├── entity_manager.rb │ ├── hooks.rb │ ├── infectors.rb │ └── infectors │ │ ├── auth_source_ldap.rb │ │ ├── group.rb │ │ └── user.rb └── tasks │ ├── ldap_sync.rake │ └── testing.rake ├── script └── ci.sh └── test ├── fixtures ├── .gitkeep ├── auth_sources.yml ├── custom_fields.yml ├── email_addresses.yml ├── groups_users.yml ├── ldap │ ├── large-ldap.lidf │ ├── names.rb │ ├── slapd.conf │ └── test-ldap.ldif ├── member_roles.yml ├── members.yml ├── projects.yml ├── roles.yml ├── settings.yml └── users.yml ├── functional └── ldap_settings_controller_test.rb ├── integration └── .gitkeep ├── performance └── auth_source_ldap_performance_test.rb ├── test_helper.rb ├── ui ├── base.rb ├── ldap_setting_test.rb └── login_test.rb └── unit ├── auth_source_ldap_test.rb ├── helpers └── ldap_settings_helper_test.rb ├── ldap_setting_test.rb └── ldap_test_test.rb /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | tmp 3 | Gemfile 4 | .svn 5 | .directory 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | sudo: false 3 | cache: 4 | directories: 5 | - workspace/redmine/vendor/bundle 6 | addons: 7 | apt: 8 | packages: 9 | - ldap-utils 10 | - slapd 11 | chrome: stable 12 | rvm: 13 | - 1.9.3 14 | - 2.3.6 15 | env: 16 | global: REDMINE_DIR=./workspace/redmine 17 | matrix: 18 | - REDMINE=3.2-stable 19 | - REDMINE=3.3-stable 20 | - REDMINE=master 21 | matrix: 22 | include: 23 | - rvm: 2.4.3 24 | env: REDMINE=3.4-stable 25 | - rvm: 2.4.3 26 | env: REDMINE=master 27 | exclude: 28 | - rvm: 1.9.3 29 | env: REDMINE=master 30 | gemfile: workspace/redmine/Gemfile 31 | bundler_args: --path vendor/bundle --gemfile workspace/redmine/Gemfile --without development rmagick 32 | before_install: 33 | - ./script/ci.sh clone_redmine --target $REDMINE_DIR 34 | - cp ./config/database.yml.travis $REDMINE_DIR/config/database.yml 35 | - ./script/ci.sh install_plugin_gemfile 36 | before_script: 37 | - mysql -e 'CREATE DATABASE redmine CHARACTER SET utf8;' 38 | - ./script/ci.sh prepare_redmine 39 | - ./script/ci.sh prepare_plugin 40 | - ./script/ci.sh start_ldap 41 | - 'phantomjs --webdriver 4444 2>&- 1>&- &' 42 | script: 43 | - ./script/ci.sh run_tests 44 | - ./script/ci.sh test_uninstall 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Redmine LDAP Sync 2 | --- forked from https://github.com/thorin/redmine_ldap_sync, which is unmaintained. 3 | This maintained version is tested working fine with Redmine4.x/Ruby2.6.x/Rails5.2.x 4 | Issues and PRs are welcome. 5 | Redmine site: http://www.redmine.org/plugins/redmine_ldap_sync 6 | 7 | Original readme: 8 | ================= 9 | 10 | This redmine plugin extends the ldap authentication with user/group 11 | synchronization. 12 | 13 | __Features__: 14 | 15 | * Synchronization of user fields and groups on login. 16 | * Detects and disables users that have been removed from LDAP. 17 | * Detects and disables users that have been marked as disabled on Active 18 | Directory (see [MS KB Article 305144][uacf] for details). 19 | * Can detect and include nested groups. Upon login the nested groups are 20 | retrieved from disk cache. This cache can only be updated with the rake task. 21 | * A rake task is available for manual or periodic synchronization of groups and 22 | users. 23 | 24 | __Remarks__: 25 | 26 | * The plugin is prepared and intended to run with any LDAP directory. But, the 27 | author can only guarantee it to work correctly with Active Directory and 28 | Slapd. 29 | * An user will only be removed from groups that exist on LDAP. This behaviour 30 | is intended as it allows both ldap and non-ldap groups to coexist. 31 | * Deleted groups on LDAP will not be deleted on redmine. 32 | 33 | Installation & Upgrade 34 | ---------------------- 35 | 36 | ### Install/Upgrade 37 | 38 | 1. **install.** - Copy your plugin directory into `#{RAILS_ROOT}/plugins`. 39 | If you are downloading the plugin directly from GitHub, you can do so by 40 | changing into the `#{RAILS_ROOT}/plugins` directory and issuing the command: 41 | ``` 42 | git clone git://github.com/tainewoo/redmine_ldap_sync.git 43 | ``` 44 | 45 | **upgrade** - Backup and replace the old plugin directory with the new 46 | plugin files. If you are downloading the plugin directly from GitHub, you 47 | can do so by changing into the plugin directory and issuing the command 48 | `git pull`. 49 | 50 | 2. Update the ruby gems by changing into the redmine's directory and run the 51 | following command. 52 | ``` 53 | bundle install 54 | ``` 55 | 56 | 3. **upgrade** - Still on the redmine's directory, run the following command 57 | to upgrade your database (make a db backup before). 58 | ``` 59 | rake redmine:plugins:migrate RAILS_ENV=production 60 | ``` 61 | 62 | 4. Change into redmine's directory `#{RAILS_ROOT}` and run the following 63 | command. 64 | ``` 65 | rake -T redmine:plugins:ldap_sync RAILS_ENV=production 66 | ``` 67 | If the installation/upgrade was successful you should now see the list of 68 | [Rake Tasks](#rake-tasks). 69 | 70 | 5. Restart Redmine. 71 | 72 | You should now be able to see **Redmine LDAP Sync** listed among the plugins in 73 | `Administration -> Plugins`. 74 | 75 | ### Uninstall 76 | 77 | 1. Change into redmine's directory `#{RAILS_ROOT}` and run the following 78 | command to downgrade the database (make a db backup before): 79 | ``` 80 | rake redmine:plugins:migrate NAME=redmine_ldap_sync VERSION=0 RAILS_ENV=production 81 | ``` 82 | 83 | 2. Remove the plugin from the plugins folder: `#{RAILS_ROOT}/plugins` 84 | 3. Restart Redmine. 85 | 86 | Usage 87 | ----- 88 | 89 | ### Configuration 90 | 91 | Open `Administration > Ldap Synchronization` to access the plugin 92 | configuration: 93 | 94 | **LDAP settings:** 95 | 96 | + **Base settings** - Preloads the configuration with predefined settings. 97 | + **Group base DN** - The path to where the groups are located. Eg, 98 | `ou=people,dc=smokeyjoe,dc=com`. 99 | + **Groups objectclass** - The groups object class. 100 | + **Users objectclass** - The users object class. 101 | + **Users search scope** - One level or whole subtree. 102 | - **One level**: searches one level below the user base DN, i.e. all its immediate children only. 103 | - **Whole subtree**: searches the whole subtree rooted at user base DN. 104 | + **Group name pattern** - (optional) An RegExp that should match up with the 105 | name of the groups that should be imported. Eg, `\.team$`. 106 | + **Group search filter** - (optional) An LDAP search filter to be applied 107 | whenever search for groups. 108 | + **Account disabled test** - A ruby boolean expression that should evaluate an 109 | account's flags (the variable `flags`) and return `true` if the account is 110 | disabled. Eg., `flags.to_i & 2 != 0` or `flags.include? 'D'`. 111 | + **Group membership** - Specifies how to determine the user's group 112 | membership. 113 | The possible values are: 114 | - **On the group class**: membership determined from the list of users 115 | contained on the group. 116 | - **On the user class**: membership determined from the list of groups 117 | contained on the user. 118 | + **Enable nested groups** - Enables and specifies how to identify the groups 119 | nesting. When enabled the plugin will look for the groups' parent groups, and 120 | so on, and add those groups to the users. The possible values are: 121 | - **Membership on the parent class**: group membership determined from the 122 | list of groups contained on the parent group. 123 | - **Membership on the member class**: group membership determined from the 124 | list of groups contained on the member group. 125 | 126 | **LDAP attributes:** 127 | 128 | + **Group name (group)** - The ldap attribute from where to fetch the 129 | group's name. Eg, `sAMAccountName`. 130 | + **Account flags (user)** - The ldap attribute containing the account disabled 131 | flag. Eg., `userAccountControl`. 132 | + **Primary group (user)** - The ldap attribute that identifies the primary 133 | group of the user. This attribute will also be used as group id when 134 | searching for the group. Eg, `gidNumber` 135 | + **Members (group)** - The ldap attribute from where to fetch the 136 | group's members. Visible if the group membership is __on the group class__. 137 | Eg, `member`. 138 | + **Memberid (user)** - The ldap attribute from where to fetch the 139 | user's memberid. This attribute must match with the __members attribute__. 140 | Visible if the group membership is __on the group class__. Eg, `dn`. 141 | + **Groups (user)** - The ldap attribute from where to fetch the user's 142 | groups. Visible if the group membership is __on the user class__. Eg, 143 | `memberof`. 144 | + **Groupid (group)** - The ldap attribute from where to fetch the 145 | group's groupid. This attribute must match with the __groups attribute__. 146 | Visible if the group membership is __on the user class__. Eg, 147 | `distinguishedName`. 148 | + **Member groups (group)** - The ldap attribute from where to fetch the 149 | group's member groups. Visible if the nested groups __membership is on the 150 | parent class__. Eg, `member`. 151 | + **Memberid attribute (group)** - The ldap attribute from where to fetch the 152 | member group's memberid. This attribute must match with the __member groups 153 | attribute__. Eg, `distinguishedName`. 154 | + **Parent groups (group)** - The ldap attribute from where to fetch 155 | the group's parent groups. Visible if the nested groups __membership is on 156 | the member class__. Eg, `memberOf`. 157 | + **Parentid attribute (group)** - The ldap attribute from where to fetch the 158 | parent group's id. This attribute must match with the __parent groups 159 | attribute__. Eg, `distinguishedName`. 160 | 161 | **Synchronization actions:** 162 | 163 | + **Users must be members of** - (optional) A group to wich the users must 164 | belong to to have access enabled to redmine. 165 | + **Administrators group** - (optional) All members of this group will become 166 | redmine administrators. 167 | + **Add users to group** - (optional) A group to wich all the users created 168 | from this LDAP authentication will added upon creation. This group should not 169 | exist on LDAP. 170 | + **Create new groups** - If enabled, groups that don't already exist on 171 | redmine will be created. 172 | + **Create new users** - If enabled, users that don't already exist on redmine 173 | will be created when running the rake task. 174 | + **Synchronize on login** - Enables/Disables users synchronization on login. 175 | The possible values are: 176 | - **User fields and groups**: Both the fields and groups will be 177 | synchronized on login. If a user is disabled 178 | on LDAP or removed from the *users must be 179 | member of* group, the user will be locked and 180 | the access denied. 181 | - **User fields**: Only the fields will be synchronized on login. If a user 182 | is disabled on LDAP, the user will be locked and the 183 | access denied. Changes on groups will not lock the user. 184 | - **Disabled**: No synchronization is done on login. 185 | + **Dynamic groups**[¹](#license) - Enables/Disables dynamic groups. The 186 | possible values are: 187 | - **Enabled**: While searching for groups, *Ldap Sync* will also search for 188 | dynamic groups. 189 | - **Enabled with a ttl**: The dynamic groups cache[²](#license) will expire 190 | every **t** minutes. 191 | - **Disabled**: *Ldap Sync* will not search for dynamic groups. 192 | + **User/Group fields:** 193 | - **Synchronize** - If enabled, the selected field will be synchronized 194 | both on the rake tasks and after every login. 195 | - **LDAP attribute** - The ldap attribute to be used as reference on the 196 | synchronization. 197 | - **Default value** - Shows the value that will be used as default. 198 | 199 | ### Rake tasks 200 | 201 | The following tasks are available: 202 | 203 | # rake -T redmine:plugins:ldap_sync 204 | rake redmine:plugins:ldap_sync:sync_all # Synchronize both redmine's users and groups with LDAP 205 | rake redmine:plugins:ldap_sync:sync_groups # Synchronize redmine's groups fields with those on LDAP 206 | rake redmine:plugins:ldap_sync:sync_users # Synchronize redmine's users fields and groups with those on LDAP 207 | 208 | This tasks can be used to do periodic synchronization. 209 | For example: 210 | 211 | # Synchronize users with ldap @ every 60 minutes 212 | 35 * * * * www-data /usr/bin/rake -f /opt/redmine/Rakefile --silent redmine:plugins:ldap_sync:sync_users RAILS_ENV=production 2>&- 1>&- 213 | 214 | The tasks recognize three environment variables: 215 | + **DRY_RUN** - Performs a run without changing the database. 216 | + **ACTIVATE_USERS** - Activates users if they're active on LDAP. 217 | + **LOG_LEVEL** - Controls the rake task verbosity. 218 | The possible values are: 219 | - **silent**: Nothing is written to the output. 220 | - **error**: Only errors are written to the output. 221 | - **change**: Only writes errors and changes made to the user/group's base. 222 | - **debug**: Detailed information about the execution is visible to help 223 | identify errors. This is the default value. 224 | 225 | ### Base settings 226 | 227 | All the base settings are loaded from the plain YAML file 228 | `config/base_settings.yml`. 229 | Please be aware that those settings weren't tested and may not work. 230 | Saying so, I'll need your help to make these settings more accurate. 231 | 232 | License 233 | ------- 234 | This plugin is released under the GPL v3 license. See LICENSE for more 235 | information. 236 | 237 | Unmaintained 238 | ------------ 239 | 240 | I created this plugin to solve a need we had on my previous job. 241 | Things changed and now I no longer have the time or the need necessary to maintain it. 242 | Sorry for this. Please consider forking or using one of the existing forks. 243 | In a best scenario, an official fork might already exist. 244 | 245 | --- 246 | 1. For details about dynamic groups see 247 | [OpenLDAP Overlays - Dynamic Lists][overlays-dynlist] or 248 | [slapo-dynlist(5) - Linux man page][slapo-dynlist]. 249 | 2. Searching for an user's dynamic groups is an costly task. To easy it up, a 250 | cache is used to store the relationship between dynamic groups and users. 251 | When running the rake task this cache will be refreshed. 252 | 253 | [uacf]: http://support.microsoft.com/kb/305144 254 | [overlays-dynlist]: http://www.openldap.org/doc/admin24/overlays.html#Dynamic%20Lists 255 | [slapo-dynlist]: http://www.openldap.org/software/man.cgi?query=slapo-dynlist 256 | -------------------------------------------------------------------------------- /app/controllers/ldap_settings_controller.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | class LdapSettingsController < ApplicationController 19 | layout 'admin' 20 | menu_item :ldap_sync 21 | 22 | before_action :require_admin 23 | before_action :find_ldap_setting, :only => [:show, :edit, :update, :test, :enable, :disable] 24 | before_action :update_ldap_setting_from_params, :only => [:edit, :update, :test] 25 | 26 | if respond_to? :skip_before_action 27 | skip_before_action :verify_authenticity_token, :if => :js_request? 28 | end 29 | 30 | # GET /ldap_settings 31 | def index 32 | @ldap_settings = LdapSetting.all 33 | 34 | respond_to do |format| 35 | format.html # index.html.erb 36 | end 37 | end 38 | 39 | # GET /ldap_settings/base_settings.js 40 | def base_settings 41 | respond_to do |format| 42 | format.js # base_settings.js.erb 43 | end 44 | end 45 | 46 | # GET /ldap_settings/1 47 | def show 48 | redirect_to edit_ldap_setting_path(@ldap_setting) 49 | end 50 | 51 | # GET /ldap_settings/1/edit 52 | def edit 53 | respond_to do |format| 54 | format.html # edit.html.erb 55 | end 56 | end 57 | 58 | # PUT /ldap_settings/1/disable 59 | def disable 60 | @ldap_setting.disable! 61 | 62 | flash[:notice] = l(:text_ldap_setting_successfully_updated); redirect_to_referer_or ldap_settings_path 63 | end 64 | 65 | # PUT /ldap_settings/1/enable 66 | def enable 67 | @ldap_setting.active = true 68 | 69 | respond_to do |format| 70 | if @ldap_setting.save 71 | format.html { flash[:notice] = l(:text_ldap_setting_successfully_updated); redirect_to_referer_or ldap_settings_path } 72 | else 73 | format.html { flash[:error] = l(:error_cannot_enable_with_invalid_settings); redirect_to_referer_or ldap_settings_path } 74 | end 75 | end 76 | end 77 | 78 | # GET /ldap_settings/1/test 79 | def test 80 | return render 'ldap_setting_invalid' unless @ldap_setting.valid? 81 | 82 | ldap_test = params[:ldap_test] 83 | users = ldap_test.fetch(:test_users, '').split(',') 84 | groups = ldap_test.fetch(:test_groups, '').split(',') 85 | [users, groups].each {|l| l.map(&:strip).reject(&:blank?) } 86 | 87 | 88 | @test = LdapTest.new(@ldap_setting) 89 | @test.bind_user = ldap_test[:bind_user] 90 | @test.bind_password = ldap_test[:bind_password] 91 | 92 | if @test.valid? 93 | @test.run_with_users_and_groups(users, groups) 94 | else 95 | render 'ldap_test_invalid' 96 | end 97 | end 98 | 99 | # PUT /ldap_settings/1 100 | def update 101 | respond_to do |format| 102 | if @ldap_setting.save 103 | format.html { flash[:notice] = l(:text_ldap_setting_successfully_updated); redirect_to_referer_or ldap_settings_path } 104 | else 105 | format.html { render 'edit' } 106 | end 107 | end 108 | end 109 | 110 | private 111 | 112 | def js_request? 113 | request.format.js? 114 | end 115 | 116 | def update_ldap_setting_from_params 117 | %w(user group).each do |e| 118 | params[:ldap_setting]["#{e}_fields_to_sync"] = params["#{e}_fields_to_sync"] 119 | params[:ldap_setting]["#{e}_ldap_attrs"] = params["#{e}_ldap_attrs"] 120 | end if params[:ldap_setting] 121 | @ldap_setting.safe_attributes = params[:ldap_setting] if params[:ldap_setting] 122 | end 123 | 124 | def find_ldap_setting 125 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(params[:id]) 126 | render_404 if @ldap_setting.nil? 127 | end 128 | end 129 | -------------------------------------------------------------------------------- /app/helpers/ldap_settings_helper.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSettingsHelper 19 | def config_css_classes(config) 20 | "ldap_setting #{config.active? ? 'enabled' : 'disabled' }" 21 | end 22 | 23 | def change_status_link(config) 24 | if config.active? 25 | link_to l(:button_disable), disable_ldap_setting_path(config), :method => :put, :class => 'icon icon-disable' 26 | else 27 | link_to l(:button_enable), enable_ldap_setting_path(config), :method => :put, :class => 'icon icon-enable' 28 | end 29 | end 30 | 31 | def ldap_setting_tabs(form) 32 | [ 33 | {:name => 'LdapSettings', :partial => 'ldap_settings', :label => :label_ldap_settings, :form => form}, 34 | {:name => 'SynchronizationActions', :partial => 'synchronization_actions', :label => :label_synchronization_actions, :form => form}, 35 | {:name => 'Test', :partial => 'test', :label => :label_test, :form => form} 36 | ] 37 | end 38 | 39 | def options_for_nested_groups 40 | [ 41 | [l(:option_nested_groups_disabled), ''], 42 | [l(:option_nested_groups_on_parents), :on_parents], 43 | [l(:option_nested_groups_on_members), :on_members] 44 | ] 45 | end 46 | 47 | def options_for_group_membeship 48 | [ 49 | [l(:option_group_membership_on_groups), :on_groups], 50 | [l(:option_group_membership_on_members), :on_members] 51 | ] 52 | end 53 | 54 | def options_for_dyngroups 55 | [ 56 | [l(:option_dyngroups_disabled), ''], 57 | [l(:option_dyngroups_enabled), :enabled], 58 | [l(:option_dyngroups_enabled_with_ttl), :enabled_with_ttl] 59 | ] 60 | end 61 | 62 | def options_for_sync_on_login 63 | [ 64 | [l(:option_sync_on_login_user_fields_and_groups), :user_fields_and_groups], 65 | [l(:option_sync_on_login_user_fields), :user_fields], 66 | [l(:option_sync_on_login_disabled), ''] 67 | ] 68 | end 69 | 70 | def options_for_users_search_scope 71 | [ 72 | [l(:option_users_search_subtree), :subtree], 73 | [l(:option_users_search_onelevel), :onelevel] 74 | ] 75 | end 76 | 77 | def group_fields 78 | has_group_ldap_attrs = @ldap_setting.has_group_ldap_attrs? 79 | 80 | GroupCustomField.all.map do |f| 81 | SyncField.new( 82 | f.id, 83 | f.name, 84 | f.is_required?, 85 | @ldap_setting.sync_group_fields? && @ldap_setting.group_fields_to_sync.include?(f.id.to_s), 86 | has_group_ldap_attrs ? @ldap_setting.group_ldap_attrs[f.id.to_s] : '', 87 | f.default_value 88 | ) 89 | end 90 | end 91 | 92 | def user_fields 93 | has_user_ldap_attrs = @ldap_setting.has_user_ldap_attrs? 94 | 95 | (User::STANDARD_FIELDS + UserCustomField.all).map do |f| 96 | if f.is_a?(String) 97 | id = f 98 | name = l("field_#{f}") 99 | required = true 100 | ldap_attr = @ldap_setting.auth_source_ldap.send("attr_#{f}") 101 | default = '' 102 | else 103 | id = f.id 104 | name = f.name 105 | required = f.is_required? 106 | ldap_attr = has_user_ldap_attrs ? @ldap_setting.user_ldap_attrs[id.to_s] : '' 107 | default = f.default_value 108 | end 109 | 110 | sync = @ldap_setting.sync_user_fields? && @ldap_setting.user_fields_to_sync.include?(id.to_s) 111 | 112 | SyncField.new(id, name, required, sync, ldap_attr, default) 113 | end 114 | end 115 | 116 | def options_for_base_settings 117 | options = [[l(:option_custom), '']] 118 | options += base_settings.collect {|k, h| [h['name'], k] }.sort 119 | options_for_select(options, current_base) 120 | end 121 | 122 | def user_fields_list(fields, group_changes) 123 | text = fields.map do |(k, v)| 124 | " #{user_field_name k} = #{v}\n" 125 | end.join 126 | groups = group_changes[:added].to_a.inspect 127 | text << " #{l(:label_group_plural)} = #{groups}\n" 128 | end 129 | 130 | def group_fields_list(fields) 131 | return " #{l(:label_no_fields)}\n" if fields.empty? 132 | 133 | fields.map do |(k, v)| 134 | " #{group_field_name k} = #{v}\n" 135 | end.join 136 | end 137 | 138 | private 139 | def user_field_name(field) 140 | return l("field_#{field}") if field !~ /\A\d+\z/ 141 | 142 | UserCustomField.find_by_id(field.to_i).name 143 | end 144 | 145 | def group_field_name(field) 146 | GroupCustomField.find_by_id(field.to_i).name 147 | end 148 | 149 | def baseable_fields 150 | LdapSetting::LDAP_ATTRIBUTES + LdapSetting::CLASS_NAMES + %w( group_membership nested_groups ) 151 | end 152 | 153 | def current_base 154 | base_settings.each do |key, hash| 155 | return key if hash.slice(*baseable_fields).all? {|k,v| @ldap_setting.send(k) == (v || '') } 156 | end 157 | '' 158 | end 159 | 160 | def base_settings 161 | @base_settings if defined? @base_settings 162 | 163 | config_dir = File.join(Redmine::Plugin.find(:redmine_ldap_sync).directory, 'config') 164 | default = baseable_fields.inject({}) {|h, k| h[k] = ''; h } 165 | @base_settings = YAML::load_file(File.join(config_dir, 'base_settings.yml')) 166 | @base_settings.each {|k,h| h.reverse_merge!(default) } 167 | end 168 | 169 | class SyncField < Struct.new :id, :name, :required, :synchronize, :ldap_attribute, :default_value 170 | def synchronize?; synchronize; end 171 | def required?; required; end 172 | end 173 | end 174 | -------------------------------------------------------------------------------- /app/models/ldap_setting.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | class LdapSetting 19 | include Redmine::SafeAttributes 20 | include Redmine::I18n 21 | 22 | include ActiveModel::Validations 23 | include ActiveModel::Validations::Callbacks 24 | include ActiveModel::Conversion 25 | extend ActiveModel::Naming 26 | include ActiveModel::AttributeMethods 27 | 28 | # LDAP_DESCRIPTORS 29 | LDAP_ATTRIBUTES = %w( groupname member user_memberid user_groups groupid parent_group primary_group group_parentid member_group group_memberid account_flags ) 30 | CLASS_NAMES = %w( class_user class_group ) 31 | FLAGS = %w( create_groups create_users active ) 32 | COMBOS = %w( group_membership nested_groups sync_on_login dyngroups users_search_scope ) 33 | OTHERS = %w( account_locked_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 ) 34 | 35 | validates_presence_of :auth_source_ldap_id 36 | validates_presence_of :class_user, :class_group, :groupname 37 | validates_presence_of :member, :user_memberid, :if => :membership_on_groups? 38 | validates_presence_of :user_groups, :groupid, :if => :membership_on_members? 39 | validates_presence_of :parent_group, :group_parentid, :if => :nested_on_members? 40 | validates_presence_of :member_group, :group_memberid, :if => :nested_on_parents? 41 | validates_presence_of :dyngroups_cache_ttl, :if => :dyngroups_enabled_with_ttl? 42 | 43 | validates_inclusion_of :nested_groups, :in => ['on_members', 'on_parents', ''] 44 | validates_inclusion_of :group_membership, :in => ['on_groups', 'on_members'] 45 | validates_inclusion_of :sync_on_login, :in => ['user_fields', 'user_fields_and_groups', ''] 46 | validates_inclusion_of :dyngroups, :in => ['enabled', 'enabled_with_ttl', ''] 47 | validates_inclusion_of :users_search_scope, :in => ['onelevel', 'subtree'] 48 | 49 | validates_format_of *(LDAP_ATTRIBUTES + [{ :with => /\A[a-z][a-z0-9-]*\z/i, :allow_blank => true }]) 50 | 51 | validates_numericality_of :dyngroups_cache_ttl, :only_integer => true, :allow_blank => true 52 | 53 | validate :validate_groupname_pattern 54 | validate :validate_account_locked_test 55 | validate :validate_group_filter 56 | validate :validate_user_fields_to_sync, :validate_user_ldap_attrs 57 | validate :validate_group_fields_to_sync, :validate_group_ldap_attrs 58 | 59 | before_validation :strip_names, :set_ldap_attrs, :set_fields_to_sync 60 | 61 | delegate :base_dn, :account, :account_password, :filter, :to => :auth_source_ldap 62 | 63 | attribute_method_affix :prefix => 'has_', :suffix => '?' 64 | attribute_method_suffix '?', '=' 65 | 66 | safe_attributes *(LDAP_ATTRIBUTES + CLASS_NAMES + FLAGS + COMBOS + OTHERS) 67 | define_attribute_methods LDAP_ATTRIBUTES + CLASS_NAMES + FLAGS + COMBOS + OTHERS 68 | ::User::STANDARD_FIELDS = %w( firstname lastname mail ) 69 | 70 | [:login, *User::STANDARD_FIELDS].each {|f| module_eval("def #{f}; auth_source_ldap.attr_#{f}; end") } 71 | 72 | def id 73 | @auth_source_ldap_id 74 | end 75 | 76 | def to_key 77 | return nil unless persisted? 78 | id ? [id] : nil 79 | end 80 | 81 | def name 82 | auth_source_ldap.name 83 | end 84 | 85 | def active? 86 | return @active if defined? @active 87 | 88 | @active = [true, '1', 'yes'].include? active 89 | end 90 | 91 | def active=(value) 92 | @active = value 93 | @attributes[:active] = value 94 | end 95 | 96 | def nested_groups_enabled? 97 | self.active? && nested_groups.present? 98 | end 99 | 100 | def nested_on_members? 101 | self.active? && nested_groups == 'on_members' 102 | end 103 | 104 | def nested_on_parents? 105 | self.active? && nested_groups == 'on_parents' 106 | end 107 | 108 | def membership_on_groups? 109 | self.active? && group_membership == 'on_groups' 110 | end 111 | 112 | def membership_on_members? 113 | self.active? && group_membership == 'on_members' 114 | end 115 | 116 | def sync_user_fields? 117 | has_user_fields_to_sync? 118 | end 119 | 120 | def sync_group_fields? 121 | has_group_fields_to_sync? 122 | end 123 | 124 | def sync_dyngroups? 125 | has_dyngroups? 126 | end 127 | 128 | def dyngroups_enabled_with_ttl? 129 | dyngroups == 'enabled_with_ttl' 130 | end 131 | 132 | def sync_on_login? 133 | active? && has_sync_on_login? 134 | end 135 | 136 | def sync_groups_on_login? 137 | sync_on_login == 'user_fields_and_groups' 138 | end 139 | 140 | def sync_fields_on_login? 141 | has_sync_on_login? 142 | end 143 | 144 | # Returns the evaluated proc of the account disabled test 145 | def account_locked_proc 146 | @account_locked_proc ||= if has_account_locked_test? 147 | eval("lambda { |flags| #{account_locked_test} }") 148 | end 149 | end 150 | 151 | # Returns the evaluated regular expression of groupname pattern 152 | def groupname_regexp 153 | @groupname_regexp ||= /#{groupname_pattern}/i 154 | end 155 | 156 | # Returns an array of ldap attributes to used when syncing the user fields 157 | def user_ldap_attrs_to_sync(fields = user_fields_to_sync) 158 | (fields||[]).map {|f| user_ldap_attrs[f] || (send(f.to_sym) if respond_to?(f.to_sym)) } 159 | end 160 | 161 | # Returns an array of ldap attributes to used when syncing the group fields 162 | def group_ldap_attrs_to_sync 163 | (group_fields_to_sync||[]).map {|f| group_ldap_attrs[f] } 164 | end 165 | 166 | # Returns the ldap attributes for the given fields 167 | # (not valid for custom fields) 168 | def ldap_attributes(*names) 169 | names.map {|n| send(n) } 170 | end 171 | 172 | # Returns the group field name for the given ldap attribute 173 | def group_field(ldap_attr) 174 | ldap_attr = ldap_attr.to_s 175 | group_ldap_attrs.find {|(k, v)| v.downcase == ldap_attr }.try(:first) 176 | end 177 | 178 | # Returns the user field name for the given ldap attribute 179 | def user_field(ldap_attr) 180 | ldap_attr = ldap_attr.to_s 181 | result = @user_standard_ldap_attrs.find {|(k, v)| v.downcase == ldap_attr }.try(:first) 182 | result ||= user_ldap_attrs.find {|(k, v)| v.downcase == ldap_attr }.try(:first) 183 | end 184 | 185 | def test 186 | @ldap_test ||= LdapTest.new(self) 187 | end 188 | 189 | def ldap_filter 190 | auth_source_ldap.send :ldap_filter 191 | end 192 | 193 | def users_search_onelevel? 194 | users_search_scope == 'onelevel' 195 | end 196 | 197 | # Creates a new ldap setting for the given ldap authentication source 198 | def initialize(source) 199 | @attributes = HashWithIndifferentAccess.new 200 | 201 | self.auth_source_ldap = source 202 | @attributes.merge!(settings) 203 | @user_standard_ldap_attrs = User::STANDARD_FIELDS.each_with_object({}) {|f, h| h[f] = (send(f)||'').downcase } 204 | end 205 | 206 | def auth_source_ldap_id=(id) 207 | @auth_source_ldap_id = id 208 | source = AuthSourceLdap.find_by_id(id) 209 | self.auth_source_ldap = source unless source.nil? 210 | end 211 | 212 | def auth_source_ldap 213 | @auth_source_ldap 214 | end 215 | 216 | def auth_source_ldap=(source) 217 | @auth_source_ldap = source 218 | @auth_source_ldap_id = source.id 219 | @attributes[:auth_source_ldap_id] = source.id 220 | end 221 | 222 | # Sets attributes from attrs that are safe 223 | # attrs is a Hash with string keys 224 | def safe_attributes=(attrs, user = User.current) 225 | if attrs.respond_to?(:to_unsafe_hash) 226 | attrs = attrs.to_unsafe_hash 227 | end 228 | @attributes.merge!(delete_unsafe_attributes(attrs, user)) 229 | end 230 | 231 | def save 232 | return false if invalid? 233 | 234 | self.settings = delete_unsafe_attributes(@attributes, User.current) 235 | end 236 | 237 | # Disables this ldap auth source 238 | # A disabled ldap auth source will not be synchronized 239 | def disable! 240 | self.active = false 241 | self.settings = settings.merge(:active => false) 242 | end 243 | 244 | # Overriden to enable validation (see ActiveModel::Validations#read_attribute_for_validation) 245 | def read_attribute_for_validation(key) 246 | @attributes[key] 247 | end 248 | 249 | # LdapSettings are always persisted because its authsource exists 250 | # (see ActiveModel::Lint::Tests::test_persisted?) 251 | def persisted? 252 | true 253 | end 254 | 255 | # Returns the name of an attribute to be displayed on the edit page 256 | def self.human_attribute_name(attr, *args) 257 | attr = attr.to_s.sub(/_id$/, '') 258 | 259 | l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr]) 260 | end 261 | 262 | # Find the ldap setting for a given ldap auth source 263 | def self.find_by_auth_source_ldap_id(id) 264 | return unless source = AuthSourceLdap.find_by_id(id) 265 | 266 | LdapSetting.new(source) 267 | end 268 | 269 | # Find all the available ldap settings 270 | def self.all(options = {}) 271 | AuthSourceLdap.where(options). 272 | map {|source| find_by_auth_source_ldap_id(source.id) }. 273 | compact 274 | end 275 | 276 | protected 277 | 278 | def validate_account_locked_test 279 | if account_locked_test.present? 280 | eval "lambda { |flags| #{account_locked_test} }" 281 | end 282 | rescue Exception => e 283 | errors.add :account_locked_test, :invalid_expression, :error_message => e.message.gsub(/^(\(eval\):1: )?(.*?)(lambda.*|$)/m, '\2') 284 | Rails.logger.error "#{e.message}\n #{e.backtrace.join("\n ")}" 285 | end 286 | 287 | def validate_groupname_pattern 288 | /#{groupname_pattern}/ if groupname_pattern.present? 289 | rescue Exception => e 290 | errors.add :groupname_pattern, :invalid_regexp, :error_message => e.message 291 | end 292 | 293 | def validate_group_filter 294 | Net::LDAP::Filter.construct(group_search_filter) if group_search_filter.present? 295 | rescue Net::LDAP::Error 296 | errors.add :group_search_filter, :invalid 297 | end 298 | 299 | def validate_user_ldap_attrs 300 | validate_ldap_attrs user_ldap_attrs, UserCustomField.all 301 | end 302 | 303 | def validate_user_fields_to_sync 304 | validate_fields user_fields_to_sync, (User::STANDARD_FIELDS + UserCustomField.all), user_ldap_attrs 305 | end 306 | 307 | def validate_group_ldap_attrs 308 | validate_ldap_attrs group_ldap_attrs, GroupCustomField.all 309 | end 310 | 311 | def validate_group_fields_to_sync 312 | validate_fields group_fields_to_sync, GroupCustomField.all, group_ldap_attrs 313 | end 314 | 315 | def validate_ldap_attrs(ldap_attrs, fields) 316 | field_ids = fields.map {|f| f.id.to_s } 317 | ldap_attrs.each do |k, v| 318 | if !field_ids.include?(k) 319 | errors.add :user_group_fields, :invalid unless errors.added? :user_group_fields, :invalid 320 | 321 | elsif v.present? && v !~ /\A[a-z][a-z0-9-]*\z/i 322 | field_name = fields.find {|f| f.id == k.to_i }.name 323 | errors.add :base, :invalid_ldap_attribute, :field => field_name 324 | end 325 | end 326 | end 327 | 328 | def validate_fields(fields_to_sync, fields, attrs) 329 | fields_ids = fields.map {|f| f.is_a?(String) ? f : f.id.to_s } 330 | if (fields_to_sync - fields_ids).present? 331 | errors.add :user_group_fields, :invalid unless errors.added? :user_group_fields, :invalid 332 | end 333 | fields_to_sync.each do |f| 334 | if f =~ /\A\d+\z/ && attrs[f].blank? 335 | field_name = fields.find {|c| !c.is_a?(String) && c.id.to_s == f }.name 336 | errors.add :base, :must_have_ldap_attribute, :field => field_name 337 | end 338 | end 339 | end 340 | 341 | private 342 | 343 | def set_fields_to_sync 344 | self.user_fields_to_sync ||= [] 345 | self.group_fields_to_sync ||= [] 346 | end 347 | 348 | def set_ldap_attrs 349 | self.user_ldap_attrs ||= {} 350 | self.group_ldap_attrs ||= {} 351 | end 352 | 353 | def strip_names 354 | LDAP_ATTRIBUTES.each {|a| @attributes[a].strip! unless @attributes[a].nil? } 355 | CLASS_NAMES.each {|a| @attributes[a].strip! unless @attributes[a].nil? } 356 | end 357 | 358 | def attributes 359 | @attributes 360 | end 361 | 362 | def attribute(attr) 363 | @attributes[attr] 364 | end 365 | 366 | def attribute=(attr, value) 367 | @attributes[attr] = value 368 | end 369 | 370 | def attribute?(attr) 371 | [true, '1', 'yes'].include? @attributes[attr] 372 | end 373 | 374 | def has_attribute?(attr) 375 | self.send("#{attr}").present? 376 | end 377 | 378 | def self.settings(source) 379 | Setting.plugin_redmine_ldap_sync.fetch(source.id, HashWithIndifferentAccess.new) 380 | end 381 | 382 | def settings 383 | LdapSetting.settings(@auth_source_ldap) 384 | end 385 | 386 | def settings=(attrs) 387 | Setting.plugin_redmine_ldap_sync = Setting.plugin_redmine_ldap_sync.merge!(@auth_source_ldap.id => attrs) 388 | end 389 | end 390 | -------------------------------------------------------------------------------- /app/models/ldap_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | class LdapTest 19 | include Redmine::I18n 20 | include LdapSync::EntityManager 21 | include ActiveModel::Conversion 22 | include ActiveModel::Validations 23 | extend ActiveModel::Naming 24 | 25 | attr_accessor :setting, :bind_user, :bind_password, :test_users, :test_groups, :messages, :user_attrs, :group_attrs, :users_at_ldap, :groups_at_ldap, :non_dynamic_groups, :dynamic_groups, :users_locked_by_group, :admin_users, :user_changes 26 | 27 | delegate :auth_source_ldap, :to => :setting 28 | delegate :users, :to => :auth_source_ldap 29 | 30 | validates_presence_of :bind_user, :bind_password, :if => :connect_as_user? 31 | 32 | def initialize(setting) 33 | setting.active = true 34 | 35 | @setting = setting 36 | @messages = '' 37 | @user_changes = {:enabled => [], :locked => [], :deleted => []} 38 | @users_at_ldap = {} 39 | @groups_at_ldap = {} 40 | @non_dynamic_groups = [] 41 | @dynamic_groups = {} 42 | @users_locked_by_group = [] 43 | @admin_users = [] 44 | end 45 | 46 | def initialize_ldap_con(login, password) 47 | auth_source_ldap.send(:initialize_ldap_con, login, password) 48 | end 49 | 50 | def run_with_users_and_groups(users, groups) 51 | with_ldap_connection(@bind_user, @bind_password) do |ldap| 52 | @user_changes = ldap_users 53 | users.each do |login| 54 | user_data = find_user(ldap, login, nil) 55 | if user_data 56 | @user_attrs ||= user_data 57 | users_at_ldap[login] = { 58 | :fields => get_user_fields(login, user_data, :include_required => true), 59 | :groups => groups_changes(User.new {|u| u.login = login }) 60 | } 61 | else 62 | users_at_ldap[login] = :not_found 63 | end 64 | end 65 | 66 | user_changes[:enabled].each do |login| 67 | group_changes = groups_changes(User.new {|u| u.login = login }) 68 | enabled_groups = group_changes[:added].map(&:downcase) 69 | 70 | if setting.has_admin_group? 71 | admin_users << login if enabled_groups.include? setting.admin_group.downcase 72 | end 73 | 74 | if setting.has_required_group? 75 | users_locked_by_group << login unless enabled_groups.include? setting.required_group.downcase 76 | end 77 | end if setting.has_admin_group? || setting.has_required_group? 78 | 79 | groups.each do |name| 80 | group_data = find_group(ldap, name, nil) 81 | if group_data 82 | @group_attrs ||= group_data 83 | groups_at_ldap[name] = { 84 | :fields => get_group_fields(name, group_data) 85 | } 86 | else 87 | groups_at_ldap[name] = :not_found 88 | end 89 | end 90 | 91 | find_all_groups(ldap, nil, n(:groupname)) do |entry| 92 | if !setting.has_groupname_pattern? || entry.first =~ /#{setting.groupname_pattern}/ 93 | non_dynamic_groups << entry.first 94 | end 95 | end 96 | if setting.sync_dyngroups? 97 | find_all_dyngroups(ldap, :update_cache => true) 98 | dynamic_groups.reject! {|(k, v)| k !~ /#{setting.groupname_pattern}/ } if setting.has_groupname_pattern? 99 | end 100 | end 101 | rescue Exception => e 102 | error(e.message + e.backtrace.join("\n ")) 103 | end 104 | 105 | def self.human_attribute_name(attr, *args) 106 | attr = attr.to_s.sub(/_id$/, '') 107 | 108 | l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr]) 109 | end 110 | 111 | def persisted?; true; end 112 | 113 | private 114 | def update_dyngroups_cache!(mem_cache) 115 | @dynamic_groups = Hash.new{|h,k| h[k] = Set.new} 116 | mem_cache.each do |(login, groups)| 117 | dyngroups_cache.write(login, groups) 118 | 119 | groups.each {|group| @dynamic_groups[group] << login } 120 | end 121 | end 122 | 123 | def closure_cache 124 | @closure_cache ||= ActiveSupport::Cache.lookup_store(:memory_store) 125 | end 126 | 127 | def dyngroups_cache 128 | @dyngroups_cache ||= ActiveSupport::Cache.lookup_store(:memory_store) 129 | end 130 | 131 | def parents_cache 132 | @parents_cache ||= ActiveSupport::Cache.lookup_store(:memory_store) 133 | end 134 | 135 | def trace(msg = "", options = {}) 136 | @messages += "#{msg}\n" if msg 137 | end 138 | 139 | def running_rake?; true; end 140 | def dyngroups_fresh?; false; end 141 | end 142 | -------------------------------------------------------------------------------- /app/views/ldap_settings/_ldap_settings.html.erb: -------------------------------------------------------------------------------- 1 | <% f = tab[:form] %> 2 | <%= error_messages_for 'ldap_setting' %> 3 |
4 |

<%= label_tag :base_settings, l(:field_base_settings) %> 5 | <%= select_tag :base_settings, options_for_base_settings %>

6 |

<%= f.text_field :groups_base_dn, :size => 50 %>

7 |

<%= f.text_field :class_user, :required => true, :size => 15 %>

8 |

<%= f.select :users_search_scope, options_for_users_search_scope %>

9 |

<%= f.text_field :class_group, :required => true, :size => 15 %>

10 |

<%= f.text_field :groupname_pattern, :size => 50 %>

11 |

<%= f.text_field :group_search_filter, :size => 50 %>

12 | 13 |

<%= f.text_field :account_locked_test, :size => 50 %>

14 |

<%= f.select :group_membership, options_for_group_membeship %>

15 |

<%= f.select :nested_groups, options_for_nested_groups %>

16 | 17 |
18 | <%=l(:label_attribute_plural)%> 19 | 20 |

<%= f.text_field :groupname, :required => true, :size => 15 %>

21 |

<%= f.text_field :account_flags, :size => 50 %>

22 |

<%= f.text_field :primary_group, :size => 15 %>

23 | 24 | 28 | 32 | 33 | 37 | 38 | 42 |
43 |
-------------------------------------------------------------------------------- /app/views/ldap_settings/_synchronization_actions.html.erb: -------------------------------------------------------------------------------- 1 | <% f = tab[:form] %> 2 | <%= error_messages_for 'ldap_setting' %> 3 |
4 |

<%= f.select :sync_on_login, options_for_sync_on_login %>

5 |

<%= f.text_field :required_group %>

6 |

<%= f.text_field :admin_group %>

7 |

<%= f.text_field :fixed_group, :size => 15 %>

8 |

<%= f.check_box :create_users %>

9 |

<%= f.check_box :create_groups %>

10 |

<%= f.select :dyngroups, options_for_dyngroups %> 11 | <%= f.text_field :dyngroups_cache_ttl, :required => true, :size => 5 %> <%= l(:label_minutes) %> 12 |

13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | 25 | 28 | 31 | 32 | 33 | 34 | <% { :user => user_fields, :group => group_fields }.each do |k, fields| %> 35 | <% if fields.any? -%> 36 | 37 | 41 | 42 | <% fields.each do |field| -%> 43 | 44 | 47 | 50 | 53 | 56 | 57 | <% end -%> 58 | <% end -%> 59 | <% end -%> 60 | 61 |
21 | <%= link_to_function(image_tag('toggle_check.png'), "toggleCheckboxesBySelector('table.fields-user-group input.sync')", 22 | :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}") %> 23 | <%= l(:label_synchronize) %> 24 | 26 | <%= l(:label_ldap_attribute) %> 27 | 29 | <%= l(:label_default_value) %> 30 |
38 |   39 | <%= l("label_#{k}") %> 40 |
45 | <%=h field.name %> <%= content_tag('span', '*', :class => 'required') if field.required? %> 46 | 48 | <%= check_box_tag "#{k}_fields_to_sync[]", field.id, field.synchronize?, :class => 'sync' %> 49 | 51 | <%= text_field_tag "#{k}_ldap_attrs[#{field.id}]", field.ldap_attribute, :size => 12, :disabled => field.id.is_a?(String) %> 52 | 54 | <%=h field.default_value %> 55 |
62 |
63 |
64 |
-------------------------------------------------------------------------------- /app/views/ldap_settings/_test.html.erb: -------------------------------------------------------------------------------- 1 | <% f = tab[:form] %> 2 | <%= error_messages_for 'ldap_test' %> 3 |
4 | <%= labelled_fields_for f.object.test do |t| -%> 5 |

<%= t.label :test_users %><%= t.text_field :test_users %>

6 |

<%= t.label :test_groups %><%= t.text_field :test_groups %>

7 | 8 | <% if t.object.connect_as_user? -%> 9 |

<%= t.label :bind_user %><%= t.text_field :bind_user %>

10 |

<%= t.label :bind_password %><%= t.text_field :bind_password %>

11 | <% end -%> 12 | 13 |

<%= link_to l(:button_execute), { :action => 'test', :format => 'text' }, 14 | :remote => true, :method => 'put', :id => 'commit-test' %>

15 |
16 |
17 | <%=l(:label_result)%> 18 | 19 |
<%=l :label_not_executed %>
20 |
21 |
22 | <% end -%> 23 |
-------------------------------------------------------------------------------- /app/views/ldap_settings/base_settings.js.erb: -------------------------------------------------------------------------------- 1 | var base_settings = <%= raw base_settings.to_json %>; -------------------------------------------------------------------------------- /app/views/ldap_settings/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= change_status_link(@ldap_setting) %> 3 |
4 | 5 |

<%= link_to l(:label_ldap_servers), ldap_settings_path %> » <%=h @ldap_setting.name %>

6 | 7 | <%= labelled_form_for @ldap_setting, :html => {:class => 'tabular'} do |f| -%> 8 | 9 | <%= render_tabs ldap_setting_tabs(f) %> 10 | 11 | <%= submit_tag l(:button_save), :id => 'commit-save' %> 12 | <% end -%> 13 | 14 | <% html_title(l(:label_ldap_synchronization)) -%> 15 | 16 | <% content_for :header_tags do %> 17 | <%= javascript_include_tag base_settings_ldap_settings_path(:format => 'js') %> 18 | <%= javascript_include_tag 'ldap_settings.js', :plugin => 'redmine_ldap_sync' %> 19 | <% end %> -------------------------------------------------------------------------------- /app/views/ldap_settings/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= l(:label_ldap_servers) %>

2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% @ldap_settings.each do |config| %> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | <% end %> 29 |
<%=l(:field_name)%><%=l(:field_host)%><%=l(:header_create_groups)%><%=l(:header_create_users)%><%=l(:header_sync_user_fields)%><%=l(:header_sync_group_fields)%>
<%= link_to h(config.name), edit_ldap_setting_path(config) %><%= config.auth_source_ldap.host %><%= checked_image config.create_groups? %><%= checked_image config.create_users? %><%= checked_image config.sync_user_fields? %><%= checked_image config.sync_group_fields? %> 24 | <%= link_to l(:button_test), edit_ldap_setting_path(config, :tab => 'Test'), :class => 'icon icon-test' %> 25 | <%= change_status_link(config) %> 26 |
30 |
-------------------------------------------------------------------------------- /app/views/ldap_settings/ldap_setting_invalid.text.erb: -------------------------------------------------------------------------------- 1 | Validation errors on the ldap settings: 2 | <% @ldap_setting.errors.full_messages.each do |msg| -%> 3 | - <%= msg %> 4 | <% end -%> -------------------------------------------------------------------------------- /app/views/ldap_settings/ldap_test_invalid.text.erb: -------------------------------------------------------------------------------- 1 | Validation errors on the test: 2 | <% @test.errors.full_messages.each do |msg| -%> 3 | - <%= msg %> 4 | <% end -%> -------------------------------------------------------------------------------- /app/views/ldap_settings/test.text.erb: -------------------------------------------------------------------------------- 1 | <% @test.users_at_ldap.each do |(login, data)| -%> 2 | <%= "#{l(:label_user)} \"#{login}\"" %>: <%= data == :not_found ? 3 | "#{l(:label_not_found)}\n" : 4 | "\n#{user_fields_list data[:fields], data[:groups]}" %> 5 | <% end -%> 6 | <% @test.groups_at_ldap.each do |(name, data)| -%> 7 | <%= "#{l(:label_group)} \"#{name}\"" %>: <%= data == :not_found ? 8 | "#{l(:label_not_found)}\n" : 9 | "\n#{group_fields_list data[:fields]}" %> 10 | <% end -%> 11 | <%=l :label_users_enabled %>: <%=l :label_a_total_of, @test.user_changes[:enabled].size %> 12 | <%= @test.user_changes[:enabled].to_a.inspect %> 13 | <% if @ldap_setting.has_account_flags? -%> 14 | 15 | <%=l :label_users_locked_by_flag %>: <%=l :label_a_total_of, @test.user_changes[:locked].size %> 16 | <%= @test.user_changes[:locked].to_a.inspect %> 17 | <% end -%> 18 | <% if @ldap_setting.has_required_group? -%> 19 | 20 | <%=l :label_users_locked_by_group %>: <%=l :label_a_total_of, @test.users_locked_by_group.size %> 21 | <%= @test.users_locked_by_group.inspect %> 22 | <% end -%> 23 | <% if @ldap_setting.has_admin_group? -%> 24 | 25 | <%=l :label_admin_users %>: <%=l :label_a_total_of, @test.admin_users.size %> 26 | <%= @test.admin_users.inspect %> 27 | <% end -%> 28 | 29 | <%=l :label_group_plural %>: <%=l :label_a_total_of, @test.non_dynamic_groups.size %> 30 | <%= @test.non_dynamic_groups.inspect %> 31 | 32 | <% if @ldap_setting.sync_dyngroups? -%> 33 | <%=l :label_dynamic_groups %>: <%=l :label_a_total_of, @test.dynamic_groups.size %> 34 | <% @test.dynamic_groups.each do |(k, v)| %> 35 | <%= k %>: <%= v.to_a.inspect %> 36 | <% end -%> 37 | 38 | <% end -%> 39 | <% if @test.user_attrs.present? -%> 40 | <%=l :label_ldap_attributes_on_a_user %>: 41 | <%= @test.user_attrs.map {|(k, v)| k }.inspect %> 42 | 43 | <% end -%> 44 | <% if @test.group_attrs.present? -%> 45 | <%=l :label_ldap_attributes_on_a_group %>: 46 | <%= @test.group_attrs.map {|(k, v)| k }.inspect %> 47 | 48 | <% end -%> 49 | <%=l :label_log_messages %>: 50 | <%= @test.messages %> -------------------------------------------------------------------------------- /assets/images/disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tainewoo/redmine_ldap_sync/95219d5f0ab007db9975a6d0f8e32e78c1f36728/assets/images/disable.png -------------------------------------------------------------------------------- /assets/images/enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tainewoo/redmine_ldap_sync/95219d5f0ab007db9975a6d0f8e32e78c1f36728/assets/images/enable.png -------------------------------------------------------------------------------- /assets/images/server_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tainewoo/redmine_ldap_sync/95219d5f0ab007db9975a6d0f8e32e78c1f36728/assets/images/server_key.png -------------------------------------------------------------------------------- /assets/javascripts/ldap_settings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | * 4 | * This file is part of Redmine LDAP Sync. 5 | * 6 | * Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Redmine LDAP Sync. If not, see . 18 | */ 19 | $(function() { 20 | "use strict"; 21 | 22 | function show_options(elem, ambit) { 23 | var selected = $(elem).val(); 24 | var prefix = '#ldap_attributes div.' + ambit; 25 | 26 | $(prefix).hide(); 27 | 28 | // Remove required for hidden elements 29 | $(prefix + ' input').removeAttr('required'); 30 | 31 | if (selected !== '') { 32 | $(prefix + '.' + selected).show(); 33 | 34 | // Add required for visible and required inputs 35 | $(prefix + '.' + selected + ' input').each(function(){ 36 | 37 | if($('label[for="' + this.id + '"]').hasClass('required')) 38 | $(this).attr('required', 'required'); 39 | 40 | }); 41 | } 42 | } 43 | 44 | function show_dyngroups_ttl(elem) { 45 | if ($(elem).val() == 'enabled_with_ttl') 46 | $('#dyngroups-cache-ttl').show(); 47 | else 48 | $('#dyngroups-cache-ttl').hide(); 49 | } 50 | 51 | show_options($('#ldap_setting_group_membership'), 'membership'); 52 | $('#ldap_setting_group_membership') 53 | .bind('change keyup', function() { show_options(this, 'membership'); }); 54 | 55 | show_options($('#ldap_setting_nested_groups'), 'nested'); 56 | $('#ldap_setting_nested_groups') 57 | .bind('change keyup', function() { show_options(this, 'nested'); }); 58 | 59 | $('#base_settings').bind('change keyup', function() { 60 | var id = $(this).val(); 61 | if (!base_settings[id]) return; 62 | 63 | var hash = base_settings[id]; 64 | for (var k in hash) if (hash.hasOwnProperty(k)) { 65 | if (k === 'name' || hash[k] === $('#ldap_setting_' + k).val()) continue; 66 | 67 | $('#ldap_setting_' + k).val(hash[k]).change() 68 | .effect('highlight', {easing: 'easeInExpo'}, 500); 69 | } 70 | }); 71 | 72 | show_dyngroups_ttl($('#ldap_setting_dyngroups')); 73 | $('#ldap_setting_dyngroups') 74 | .bind('change keyup', function() { show_dyngroups_ttl(this); }); 75 | 76 | $('input[name^="ldap_test"]').keydown(function (e) { 77 | if (e.which == 13) { 78 | $('#commit-test').click(); 79 | e.preventDefault(); 80 | } 81 | }); 82 | 83 | $('form[id^="edit_ldap_setting"]').submit(function() { 84 | var current_tab = $('a[id^="tab-"].selected').attr('id').substring(4); 85 | $('form[id^="edit_ldap_setting"]').append( 86 | '' 87 | ); 88 | }); 89 | 90 | $('#commit-test') 91 | .bind('ajax:before', function() { 92 | var data = $('form[id^="edit_ldap_setting"]').serialize(); 93 | $(this).data('params', data); 94 | }) 95 | .bind('ajax:success', function(event, data) { 96 | $('#test-result').text(data); 97 | }); 98 | }); -------------------------------------------------------------------------------- /assets/stylesheets/ldap_sync.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | * 4 | * This file is part of Redmine LDAP Sync. 5 | * 6 | * Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Redmine LDAP Sync. If not, see . 18 | */ 19 | fieldset.box legend { padding-left: 2px; background-image: none; cursor: default; } 20 | 21 | #admin-menu a.ldap-sync { background-image:url('../images/server_key.png'); } 22 | 23 | tr.ldap_setting.disabled { color: #AAAAAA; } 24 | 25 | tr.ldap_setting.disabled a { color: #AAAAAA; } 26 | 27 | .icon-disable { background-image: url("../images/disable.png"); } 28 | 29 | .icon-enable { background-image: url("../images/enable.png"); } 30 | 31 | .paragraph { padding-left: 300px; } 32 | 33 | #dyngroups-cache-ttl { display: none; } 34 | 35 | #dyngroups-cache-ttl label { float: none; margin-left: 25px; margin-right: 3px; } 36 | 37 | pre#test-result { white-space: pre-wrap; word-wrap: break-word; } -------------------------------------------------------------------------------- /config/Gemfile.travis: -------------------------------------------------------------------------------- 1 | group :test do 2 | gem 'chromedriver-helper', '~> 1.1' 3 | if RUBY_VERSION >= '2.0' 4 | gem 'coveralls', :require => false 5 | elsif RUBY_VERSION < '1.9' 6 | gem 'i18n', '~> 0.6.11' 7 | gem 'rack-cache', '= 1.2' 8 | gem 'test-unit', '~> 3.0.0' 9 | end 10 | if ENV['REDMINE'] == 'master' 11 | gem 'rails-controller-testing', '~> 1.0.2' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /config/base_settings.yml: -------------------------------------------------------------------------------- 1 | active_directory: 2 | name: Active Directory 3 | class_user: user 4 | class_group: group 5 | account_locked_test: "flags.to_i & 2 != 0" 6 | group_membership: on_members 7 | nested_groups: "" 8 | groupname: samaccountname 9 | account_flags: useraccountcontrol 10 | user_groups: memberof 11 | groupid: distinguishedname 12 | active_directory_nested: 13 | name: Active Directory (with nested groups) 14 | class_user: user 15 | class_group: group 16 | account_locked_test: "flags.to_i & 2 != 0" 17 | group_membership: on_members 18 | nested_groups: on_parents 19 | groupname: samaccountname 20 | account_flags: useraccountcontrol 21 | user_groups: memberof 22 | groupid: distinguishedname 23 | member_group: member 24 | group_memberid: distinguishedname 25 | open_ds: 26 | name: OpenDS 27 | class_user: person 28 | class_group: groupOfUniqueNames 29 | group_membership: on_members 30 | groupname: cn 31 | user_groups: isMemberOf 32 | groupid: entryDN 33 | lotus_notes_ldap: 34 | name: Lotus Notes LDAP 35 | class_user: dominoPerson 36 | class_group: dominoGroup 37 | group_membership: on_groups 38 | groupname: cn 39 | member: member 40 | user_memberid: dn 41 | open_ldap_posix_groups: 42 | name: Open LDAP (with posixGroups) 43 | class_user: posixAccount 44 | class_group: posixGroup 45 | group_membership: on_groups 46 | groupname: cn 47 | primary_group: gidNumber 48 | member: memberUid 49 | user_memberid: uid 50 | samba_ldap: 51 | name: Samba LDAP 52 | class_user: sambaSamAccount 53 | class_group: sambaGroupMapping 54 | account_locked_test: "flags.include? 'D'" 55 | group_membership: on_groups 56 | groupname: cn 57 | account_flags: sambaAcctFlags 58 | member: member 59 | user_memberid: dn 60 | novell_edirectory_nn: 61 | name: Novell eDirectory (not nested) 62 | class_user: organizationalPerson 63 | class_group: groupOfNames 64 | nested_groups: "" 65 | group_membership: on_groups 66 | groupname: cn 67 | member: member 68 | groupid: entryDN 69 | user_memberid: entryDN 70 | user_groups: groupMembership 71 | -------------------------------------------------------------------------------- /config/database.yml.travis: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: <%= RUBY_VERSION >= '1.9' ? 'mysql2' : 'mysql' %> 3 | database: redmine 4 | username: travis 5 | encoding: utf8 -------------------------------------------------------------------------------- /config/locales/de.yml: -------------------------------------------------------------------------------- 1 | de: 2 | label_ldap_synchronization: "LDAP synchronization" 3 | label_ldap_settings: "LDAP Einstellungen" 4 | label_ldap_servers: "LDAP servers" 5 | label_synchronization_actions: "Syncronizationsaktionen" 6 | label_synchronize: "Synchronize" 7 | label_ldap_attribute: "LDAP Attribut" 8 | label_default_value: "Standardeinstellung" 9 | label_test: "Testen" 10 | label_result: "Resultate" 11 | label_minutes: "minutes" 12 | 13 | label_not_executed: "Not executed" 14 | label_no_fields: "No fields" 15 | label_not_found: "Not found" 16 | label_users_enabled: "Users enabled" 17 | label_a_total_of: "a total of %{count}" 18 | label_users_locked_by_flag: "Users locked by flag" 19 | label_users_locked_by_group: "Users locked by group" 20 | label_admin_users: "Admin users" 21 | label_dynamic_grous: "Dynamic groups" 22 | label_ldap_attributes_on_a_user: "LDAP attributes on a user" 23 | label_ldap_attributes_on_a_group: "LDAP attributes on a group" 24 | label_log_messages: "Log messages" 25 | 26 | button_test: "Testen" 27 | button_execute: "Execute" 28 | button_enable: "Enable" 29 | button_disable: "Disable" 30 | 31 | header_create_groups: "Create groups" 32 | header_create_users: "Create users" 33 | header_sync_user_fields: "Benutzerattribute sync" 34 | header_sync_group_fields: "Sync group fields" 35 | 36 | field_nested_groups: "Nested groups" 37 | field_create_groups: "Neue Gruppe erstellen" 38 | field_create_users: "Create users" 39 | field_sync_on_login: "Synchronize on login" 40 | field_dyngroups: "Dynamic groups" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Gruppen DN" 44 | field_group_membership: "Group membership" 45 | field_class_user: "Benutzerobjektklasse" 46 | field_users_search_scope: "Users search scope" 47 | field_class_group: "Gruppenobjektklasse" 48 | field_account_locked_test: "Account Deaktivierungsbedingung" 49 | 50 | field_groupname_pattern: "Regular Expression für den Gruppenfilter" 51 | field_group_search_filter: "Gruppensuchfilfer" 52 | 53 | field_groupname: "Gruppenname (group)" 54 | field_member: "Gruppenteilnehmer (group)" 55 | field_member_group: "Member groups (group)" 56 | field_parent_group: "Parent groups (group)" 57 | field_user_memberid: "Memberid (user)" 58 | field_group_memberid: "Memberid (group)" 59 | field_group_parentid: "Parentid (group)" 60 | field_user_groups: "Groups (user)" 61 | field_groupid: "Groupid (group)" 62 | field_account_flags: "Account flags (user)" 63 | field_primary_group: "Primary group (user)" 64 | 65 | field_required_group: "Benutzer müssen Gruppenteilnehmer sein" 66 | field_admin_group: "Administrators group" 67 | field_fixed_group: "Benutzer zur Gruppe hinzufügen" 68 | 69 | field_user_group_fields: "User/Group fields" 70 | field_firstname: "Vorname" 71 | field_lastname: "Nachname" 72 | field_mail: "Email Adresse" 73 | 74 | field_test_users: "Benutzer" 75 | field_test_groups: "Gruppen" 76 | 77 | option_users_search_subtree: "Whole subtree" 78 | option_users_search_onelevel: "One level" 79 | 80 | option_group_membership_on_groups: "On the group class" 81 | option_group_membership_on_members: "On the user class" 82 | 83 | option_nested_groups_disabled: "Disabled" 84 | option_nested_groups_on_parents: "Membership on the parent class" 85 | option_nested_groups_on_members: "Membership on the member class" 86 | 87 | option_dyngroups_disabled: "Disabled" 88 | option_dyngroups_enabled: "Enabled" 89 | option_dyngroups_enabled_with_ttl: "Enabled with a TTL" 90 | 91 | option_sync_on_login_disabled: "Disabled" 92 | option_sync_on_login_user_fields: "User fields" 93 | option_sync_on_login_user_fields_and_groups: "User fields and groups" 94 | 95 | text_ldap_setting_successfully_updated: "Ldap configuration successfully updated." 96 | 97 | field_base_settings: "Base settings" 98 | option_custom: "Customized" 99 | 100 | error_cannot_enable_with_invalid_settings: "Cannot enable synchronization with invalid settings. Please revise the configuration." 101 | 102 | errors: 103 | messages: 104 | invalid_ldap_attribute: "%{value} has an invalid LDAP attribute" 105 | must_have_ldap_attribute: "%{value} must have an LDAP attribute for it to be synchronized" 106 | invalid_expression: "contains an invalid expression: %{error_message}" 107 | invalid_regexp: "contains an invalid regular expression: %{error_message}" -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | label_ldap_synchronization: "LDAP synchronization" 3 | label_ldap_settings: "LDAP settings" 4 | label_ldap_servers: "LDAP servers" 5 | label_synchronization_actions: "Synchronization actions" 6 | label_synchronize: "Synchronize" 7 | label_ldap_attribute: "LDAP attribute" 8 | label_default_value: "Default value" 9 | label_test: "Test" 10 | label_result: "Result" 11 | label_minutes: "minutes" 12 | 13 | label_not_executed: "Not executed" 14 | label_no_fields: "No fields" 15 | label_not_found: "Not found" 16 | label_users_enabled: "Users enabled" 17 | label_a_total_of: "a total of %{count}" 18 | label_users_locked_by_flag: "Users locked by flag" 19 | label_users_locked_by_group: "Users locked by group" 20 | label_admin_users: "Admin users" 21 | label_dynamic_groups: "Dynamic groups" 22 | label_ldap_attributes_on_a_user: "LDAP attributes on a user" 23 | label_ldap_attributes_on_a_group: "LDAP attributes on a group" 24 | label_log_messages: "Log messages" 25 | 26 | button_test: "Test" 27 | button_execute: "Execute" 28 | button_enable: "Enable" 29 | button_disable: "Disable" 30 | 31 | header_create_groups: "Create groups" 32 | header_create_users: "Create users" 33 | header_sync_user_fields: "Sync user fields" 34 | header_sync_group_fields: "Sync groups fields" 35 | 36 | field_nested_groups: "Nested groups" 37 | field_create_groups: "Create groups" 38 | field_create_users: "Create users" 39 | field_sync_on_login: "Synchronize on login" 40 | field_dyngroups: "Dynamic groups" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Groups base DN" 44 | field_group_membership: "Group membership" 45 | field_class_user: "Users objectclass" 46 | field_users_search_scope: "Users search scope" 47 | field_class_group: "Groups objectclass" 48 | field_account_locked_test: "Account disabled test" 49 | 50 | field_groupname_pattern: "Group name pattern" 51 | field_group_search_filter: "Group search filter" 52 | 53 | field_groupname: "Group name (group)" 54 | field_member: "Member users (group)" 55 | field_member_group: "Member groups (group)" 56 | field_parent_group: "Parent groups (group)" 57 | field_user_memberid: "Memberid (user)" 58 | field_group_memberid: "Memberid (group)" 59 | field_group_parentid: "Parentid (group)" 60 | field_user_groups: "Groups (user)" 61 | field_groupid: "Groupid (group)" 62 | field_account_flags: "Account flags (user)" 63 | field_primary_group: "Primary group (user)" 64 | 65 | field_required_group: "Users must be members of" 66 | field_admin_group: "Administrators group" 67 | field_fixed_group: "Add users to group" 68 | 69 | field_user_group_fields: "User/Group fields" 70 | field_firstname: "First name" 71 | field_lastname: "Last name" 72 | field_mail: "Email" 73 | 74 | field_test_users: "Users" 75 | field_test_groups: "Groups" 76 | field_bind_user: "Bind user" 77 | field_bind_password: "Bind password" 78 | 79 | option_users_search_subtree: "Whole subtree" 80 | option_users_search_onelevel: "One level" 81 | 82 | option_group_membership_on_groups: "On the group class" 83 | option_group_membership_on_members: "On the user class" 84 | 85 | option_nested_groups_disabled: "Disabled" 86 | option_nested_groups_on_parents: "Membership on the parent class" 87 | option_nested_groups_on_members: "Membership on the member class" 88 | 89 | option_dyngroups_disabled: "Disabled" 90 | option_dyngroups_enabled: "Enabled" 91 | option_dyngroups_enabled_with_ttl: "Enabled with a TTL" 92 | 93 | option_sync_on_login_disabled: "Disabled" 94 | option_sync_on_login_user_fields: "User fields" 95 | option_sync_on_login_user_fields_and_groups: "User fields and groups" 96 | 97 | text_ldap_setting_successfully_updated: "Ldap configuration successfully updated." 98 | 99 | field_base_settings: "Base settings" 100 | option_custom: "Customized" 101 | 102 | error_cannot_enable_with_invalid_settings: "Cannot enable synchronization with invalid settings. Please revise the configuration." 103 | 104 | errors: 105 | messages: 106 | invalid_ldap_attribute: "%{field} has an invalid LDAP attribute" 107 | must_have_ldap_attribute: "%{field} must have an LDAP attribute for it to be synchronized" 108 | invalid_expression: "contains an invalid expression: %{error_message}" 109 | invalid_regexp: "contains an invalid regular expression: %{error_message}" -------------------------------------------------------------------------------- /config/locales/es.yml: -------------------------------------------------------------------------------- 1 | es: 2 | label_ldap_synchronization: "Sincronización LDAP" 3 | label_ldap_settings: "Configuración LDAP" 4 | label_ldap_servers: "Servidores LDAP" 5 | label_synchronization_actions: "Acciones de sincronización" 6 | label_synchronize: "Sincronizar" 7 | label_ldap_attribute: "Atributo LDAP" 8 | label_default_value: "Valor por defecto" 9 | label_test: "Probar" 10 | label_result: "Resultado" 11 | label_minutes: "minutos" 12 | 13 | label_not_executed: "No ejecutado" 14 | label_no_fields: "Sin campos" 15 | label_not_found: "No encontrado" 16 | label_users_enabled: "Usuarios activos" 17 | label_a_total_of: "un total de %{count}" 18 | label_users_locked_by_flag: "Usuarios inhabilitados por indicadores" 19 | label_users_locked_by_group: "Usuarios inhabilitados por grupo" 20 | label_admin_users: "Administradores redmine" 21 | label_dynamic_grous: "Grupos dinámicos" 22 | label_ldap_attributes_on_a_user: "Atributos LDAP en un usuario" 23 | label_ldap_attributes_on_a_group: "Atributos LDAP en un grupo" 24 | label_log_messages: "Mensajes de log" 25 | 26 | button_test: "Probar" 27 | button_execute: "Ejecutar" 28 | button_enable: "Activar" 29 | button_disable: "Inhabilitar" 30 | 31 | header_create_groups: "Crear grupos" 32 | header_create_users: "Crear usuarios" 33 | header_sync_user_fields: "Sinc atrib usuarios" 34 | header_sync_group_fields: "Sinc atrib grupos" 35 | 36 | field_nested_groups: "Grupos anidados" 37 | field_create_groups: "Crear grupos" 38 | field_create_users: "Crear usuarios" 39 | field_sync_on_login: "Sincronizar en el inicio de sesión" 40 | field_dyngroups: "Grupos dinámicos" 41 | field_dyngroups_cache_ttl: "Caché TTL" 42 | 43 | field_groups_base_dn: "Base DN de grupos" 44 | field_group_membership: "Pertenencia al grupo" 45 | field_class_user: "Objectclass de usuarios" 46 | field_users_search_scope: "Ámbito de búsqueda de usuarios" 47 | field_class_group: "Objectclass de grupos" 48 | field_account_locked_test: "Prueba de cuenta inhabilitada" 49 | 50 | field_groupname_pattern: "Filtro regex de grupos" 51 | field_group_search_filter: "Filtro de búsqueda de grupos" 52 | 53 | field_groupname: "Nombre del grupo (grupo)" 54 | field_member: "Miembros (grupo)" 55 | field_member_group: "Grupos miembros (grupo)" 56 | field_parent_group: "Grupos padres (grupo)" 57 | field_user_memberid: "Memberid (usuario)" 58 | field_group_memberid: "Memberid (grupo)" 59 | field_group_parentid: "Parentid (grupo)" 60 | field_user_groups: "Grupos (usuario)" 61 | field_groupid: "Groupid (grupo)" 62 | field_account_flags: "Indicadores de cuenta (usuario)" 63 | field_primary_group: "Grupo primario (usuario)" 64 | 65 | field_required_group: "Bloquear si no pertenece al grupo" 66 | field_admin_group: "Administradores son miembros del grupo" 67 | field_fixed_group: "Añadir nuevos usuarios al grupo" 68 | 69 | field_user_group_fields: "Campos usuario/grupo" 70 | field_firstname: "Nombre" 71 | field_lastname: "Apellido" 72 | field_mail: "Correo electrónico" 73 | 74 | field_test_users: "Usuarios" 75 | field_test_groups: "Grupos" 76 | 77 | option_users_search_subtree: "Toda subárbol" 78 | option_users_search_onelevel: "Un nivel" 79 | 80 | option_group_membership_on_groups: "En la clase grupo" 81 | option_group_membership_on_members: "En la clase usuario" 82 | 83 | option_nested_groups_disabled: "Inhabilitado" 84 | option_nested_groups_on_parents: "Pertenencia en el padre" 85 | option_nested_groups_on_members: "Pertenencia en el miembro" 86 | 87 | option_dyngroups_disabled: "Inhabilitado" 88 | option_dyngroups_enabled: "Habilitado" 89 | option_dyngroups_enabled_with_ttl: "Habilitado con un TTL" 90 | 91 | option_sync_on_login_disabled: "Inhabilitado" 92 | option_sync_on_login_user_fields: "Campos de los usuarios" 93 | option_sync_on_login_user_fields_and_groups: "Campos y grupos de los usuarios" 94 | 95 | text_ldap_setting_successfully_updated: "Configuración LDAP actualizada con éxito." 96 | 97 | field_base_settings: "Configuración base" 98 | option_custom: "Personalizado" 99 | 100 | error_cannot_enable_with_invalid_settings: "No es posible activar la sincronización mientras haga errores en la configuración" 101 | 102 | errors: 103 | messages: 104 | invalid_ldap_attribute: "%{value} tiene un atributo LDAP no válido" 105 | must_have_ldap_attribute: "%{value} debe tener un atributo LDAP para que se pueda sincronizar" 106 | invalid_expression: "contiene una expresión no válida: %{error_message}" 107 | invalid_regexp: "contiene una expresión regular no válida: %{error_message}" 108 | -------------------------------------------------------------------------------- /config/locales/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | label_ldap_synchronization: "Synchronisation LDAP" 3 | label_ldap_settings: "Paramètres LDAP" 4 | label_ldap_servers: "Serveurs LDAP" 5 | label_synchronization_actions: "Actions de synchro." 6 | label_synchronize: "Synchroniser" 7 | label_ldap_attribute: "Attribut LDAP" 8 | label_default_value: "Valeur par défaut" 9 | label_test: "Test" 10 | label_result: "Résultat" 11 | label_minutes: "minutes" 12 | 13 | label_not_executed: "Non executé" 14 | label_no_fields: "Pas de champ" 15 | label_not_found: "Pas trouvé" 16 | label_users_enabled: "Utilisateurs activés" 17 | label_a_total_of: "un total de %{count}" 18 | label_users_locked_by_flag: "Utilisateurs désactivés par statut" 19 | label_users_locked_by_group: "Utilisateurs désactivés par groupes" 20 | label_admin_users: "Administrateurs" 21 | label_dynamic_groups: "Groupes Dynamiques" 22 | label_ldap_attributes_on_a_user: "Attributs LDAP sur un utilisateur" 23 | label_ldap_attributes_on_a_group: "Attributs LDAP sur un groupe" 24 | label_log_messages: "Messages de log" 25 | 26 | button_test: "Test" 27 | button_execute: "Executer" 28 | button_enable: "Activer" 29 | button_disable: "Désactiver" 30 | 31 | header_create_groups: "Créer groupes" 32 | header_create_users: "Créer utilisateurs" 33 | header_sync_user_fields: "Sync. champs utilisateurs" 34 | header_sync_group_fields: "Sync. champs groupes" 35 | 36 | field_nested_groups: "Groupes imbriqués" 37 | field_create_groups: "Créer des groupes" 38 | field_create_users: "Créer des utilisateurs" 39 | field_sync_on_login: "Synchroniser à la connexion" 40 | field_dyngroups: "Groupes dynamiques" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Groupes base DN" 44 | field_group_membership: "Adhésion au groupe" 45 | field_class_user: "Utilisateurs objectclass" 46 | field_users_search_scope: "Profondeur de la recherche des utilisateurs" 47 | field_class_group: "Groupes objectclass" 48 | field_account_locked_test: "Compte désactivé test" 49 | 50 | field_groupname_pattern: "Modèle de nom de groupe" 51 | field_group_search_filter: "Filtre de recherche de groupes" 52 | 53 | field_groupname: "Nom du groupe (groupe)" 54 | field_member: "Utilisateurs membres (groupe)" 55 | field_member_group: "Groupes membres (groupe)" 56 | field_parent_group: "Groupes parents (groupe)" 57 | field_user_memberid: "Memberid (utilisateur)" 58 | field_group_memberid: "Memberid (groupe)" 59 | field_group_parentid: "Parentid (groupe)" 60 | field_user_groups: "Groupes (utilisateur)" 61 | field_groupid: "Groupid (groupe)" 62 | field_account_flags: "Account flags (utilisateur)" 63 | field_primary_group: "Groupe principal (utilisateur)" 64 | 65 | field_required_group: "L'utilisateur doit être membre de" 66 | field_admin_group: "Groupe des administrateurs" 67 | field_fixed_group: "Ajouter des utilisateurs aux groupes" 68 | 69 | field_user_group_fields: "Champs utilisateur/groupe" 70 | field_firstname: "Prénom" 71 | field_lastname: "Nom" 72 | field_mail: "Email" 73 | 74 | field_test_users: "Utilisateurs" 75 | field_test_groups: "Groupes" 76 | 77 | option_users_search_subtree: "Tout le sous-arbre" 78 | option_users_search_onelevel: "Un niveau en dessous" 79 | 80 | option_group_membership_on_groups: "Sur la classe Groupe" 81 | option_group_membership_on_members: "Sur la classe Utilisateur" 82 | 83 | option_nested_groups_disabled: "Désactivé" 84 | option_nested_groups_on_parents: "Adhésion à la classe parent" 85 | option_nested_groups_on_members: "Adhésion à la classe membre" 86 | 87 | option_dyngroups_disabled: "Désactivé" 88 | option_dyngroups_enabled: "Activé" 89 | option_dyngroups_enabled_with_ttl: "Activé avec un TTL" 90 | 91 | option_sync_on_login_disabled: "Désactivé" 92 | option_sync_on_login_user_fields: "Champs utilisateurs" 93 | option_sync_on_login_user_fields_and_groups: "Champs utilisateurs et groupes" 94 | 95 | text_ldap_setting_successfully_updated: "Configuration LDAP mise à jour avec succés" 96 | 97 | field_base_settings: "Paramètres de base" 98 | option_custom: "Personnalisée" 99 | 100 | error_cannot_enable_with_invalid_settings: "Impossible d'activer la synchronisation avec des paramètres invalides. Veuillez revoir la configuration." 101 | 102 | errors: 103 | messages: 104 | invalid_ldap_attribute: "%{field} a un attribut LDAP non valide" 105 | must_have_ldap_attribute: "%{field} doit avoir un attribut LDAP pour être synchronisé" 106 | invalid_expression: "contient une expression non valide: %{error_message}" 107 | invalid_regexp: "contient une expression régulière non valide: %{error_message}" 108 | -------------------------------------------------------------------------------- /config/locales/ja.yml: -------------------------------------------------------------------------------- 1 | ja: 2 | label_ldap_synchronization: "LDAP同期" # "LDAP synchronization" 3 | label_ldap_settings: "LDAP設定" # "LDAP settings" 4 | label_ldap_servers: "LDAPサーバー" # "LDAP servers" 5 | label_synchronization_actions: "同期動作" # "Synchronization actions" 6 | label_synchronize: "同期" # "Synchronize" 7 | label_ldap_attribute: "LDAP属性" # "LDAP attribute" 8 | label_default_value: "デフォルト値" # "Default value" 9 | label_test: "テスト" # "Test" 10 | label_result: "リザルト" # "Result" 11 | label_minutes: "分" # "minutes" 12 | 13 | label_not_executed: "未実行" # "Not executed" 14 | label_no_fields: "フィールド無し" # "No fields" 15 | label_not_found: "見つかりません" # "Not found" 16 | label_users_enabled: "有効ユーザー" # "Users enabled" 17 | label_a_total_of: "%{count} 個" # "a total of %{count}" 18 | label_users_locked_by_flag: "フラグによって無効化されたユーザー" # "Users disabled by flag" 19 | label_users_locked_by_group: "グループによって無効化されたユーザー" 20 | label_admin_users: "管理者" # "Admin users" 21 | label_dynamic_groups: "ダイナミックグループ" # "Dynamic groups" 22 | label_ldap_attributes_on_a_user: "ユーザー中に在るLDAP属性" # "LDAP attributes on a user" 23 | label_ldap_attributes_on_a_group: "グループ中に在るLDAP属性" # "LDAP attributes on a group" 24 | label_log_messages: "ログメッセージ" # "Log messages" 25 | 26 | button_test: "テスト" # "Test" 27 | button_execute: "実行" # "Execute" 28 | button_enable: "有効" # "Enable" 29 | button_disable: "無効" # "Disable" 30 | 31 | header_create_groups: "グループを作成する" # "Create groups" 32 | header_create_users: "ユーザーを作成する" # "Create users" 33 | header_sync_user_fields: "ユーザーフィールドを同期する" # "Sync user fields" 34 | header_sync_group_fields: "グループフィールドを同期する" # "Sync groups fields" 35 | 36 | field_nested_groups: "ネストされたグループ" # "Nested groups" 37 | field_create_groups: "グループを作成する" # "Create groups" 38 | field_create_users: "ユーザーを作成する" # "Create users" 39 | field_sync_on_login: "ログイン時に同期" # "Synchronize on login" 40 | field_dyngroups: "ダイナミックグループ" # "Dynamic groups" 41 | field_dyngroups_cache_ttl: "キャッシュTTL" # "Cache TTL" 42 | 43 | field_groups_base_dn: "グループベースDN" # "Groups base DN" 44 | field_group_membership: "グループ メンバーシップ" # "Group membership" 45 | field_class_user: "ユーザー オブジェクトクラス" # "Users objectclass" 46 | field_users_search_scope: "Users search scope" 47 | field_class_group: "グループ オブジェクトクラス" # "Groups objectclass" 48 | field_account_locked_test: "無効アカウントの判別方法" # "Account disabled test" 49 | 50 | field_groupname_pattern: "グループネームパターン" # "Group name pattern" 51 | field_group_search_filter: "グループフィルター" # "Group search filter" 52 | 53 | field_groupname: "グループ名(group)" # "Group name (group)" 54 | field_member: "メンバーユーザー(group)" # "Member users (group)" 55 | field_member_group: "メンバーグループ(group)" # "Member groups (group)" 56 | field_parent_group: "親グループ(group)" # "Parent groups (group)" 57 | field_user_memberid: "メンバーID(user)" # "Memberid (user)" 58 | field_group_memberid: "メンバーID(group)" # "Memberid (group)" 59 | field_group_parentid: "親ID(group)" # "Parentid (group)" 60 | field_user_groups: "グループ(user)" # "Groups (user)" 61 | field_groupid: "グループID(group)" # "Groupid (group)" 62 | field_account_flags: "アカウントフラグ(user)" # "Account flags (user)" 63 | field_primary_group: "プライマリーグループ(user)" # "Primary group (user)" 64 | 65 | field_required_group: "登録必須グループ" # "Users must be members of" 66 | field_admin_group: "管理者グループ" # "Administrators group" 67 | field_fixed_group: "ユーザ追加先グループ" # "Add users to group" 68 | 69 | field_user_group_fields: "ユーザー/グループ フィールド" # "User/Group fields" 70 | field_firstname: "名前" # "First name" 71 | field_lastname: "名字" # "Last name" 72 | field_mail: "メールアドレス" # "Email" 73 | 74 | field_test_users: "ユーザー" # "Users" 75 | field_test_groups: "グループ" # "Groups" 76 | 77 | option_users_search_subtree: "Whole subtree" 78 | option_users_search_onelevel: "One level" 79 | 80 | option_group_membership_on_groups: "グループ情報中" # "On the group class" 81 | option_group_membership_on_members: "ユーザー情報中" # "On the user class" 82 | 83 | option_nested_groups_disabled: "無効" # "Disabled" 84 | option_nested_groups_on_parents: "メンバーシップは親情報中" # "Membership on the parent class" 85 | option_nested_groups_on_members: "メンバーシップは子情報中" # "Membership on the member class" 86 | 87 | option_dyngroups_disabled: "無効" # "Disabled" 88 | option_dyngroups_enabled: "有効" # "Enabled" 89 | option_dyngroups_enabled_with_ttl: "有効+持続時間指定" # "Enabled with a TTL" 90 | 91 | option_sync_on_login_disabled: "無効" # "Disabled" 92 | option_sync_on_login_user_fields: "ユーザーフィールド" # "User fields" 93 | option_sync_on_login_user_fields_and_groups: "ユーザーフィールドとグループ" # "User fields and groups" 94 | 95 | text_ldap_setting_successfully_updated: "LDAP同期設定の更新に成功しました" # "Ldap configuration successfully updated." 96 | 97 | field_base_settings: "ベースセッティング" # "Base settings" 98 | option_custom: "カスタマイズ" # "Customized" 99 | 100 | error_cannot_enable_with_invalid_settings: "設定に誤りがあり同期を有効化できませんでした、設定を修正してください。" # "Cannot enable synchronization with invalid settings. Please revise the configuration." 101 | 102 | errors: 103 | messages: 104 | invalid_ldap_attribute: "%{field} に不正なLDAP属性が在ります" # "%{field} has an invalid LDAP attribute" 105 | must_have_ldap_attribute: "同期するにはLDAP属性に %{field} が必須です" # "%{field} must have an LDAP attribute for it to be synchronized" 106 | invalid_expression: "不正な式が含まれてます: %{error_message}" # "contains an invalid expression: %{error_message}" 107 | invalid_regexp: "不正な正規表現が含まれてます: %{error_message}" # "contains an invalid regular expression: %{error_message}" 108 | -------------------------------------------------------------------------------- /config/locales/nl.yml: -------------------------------------------------------------------------------- 1 | nl: 2 | label_ldap_synchronization: "LDAP synchronisatie" 3 | label_ldap_settings: "LDAP instellingen" 4 | label_ldap_servers: "LDAP servers" 5 | label_synchronization_actions: "Synchronisatie-acties" 6 | label_synchronize: "Synchroniseren" 7 | label_ldap_attribute: "LDAP-attribuut" 8 | label_default_value: "Standaardwaarde" 9 | label_test: "Test" 10 | label_result: "Resultaat" 11 | label_minutes: "minuten" 12 | 13 | label_not_executed: "Niet uitgevoerd" 14 | label_no_fields: "Geen velden" 15 | label_not_found: "Niet gevonden" 16 | label_users_enabled: "Ingeschakelde gebruikers" 17 | label_a_total_of: "een totaal van %{count}" 18 | label_users_locked_by_flag: "Gebruikers uitgeschakeld door vlag" 19 | label_users_locked_by_group: "Gebruikers uitgeschakeld door groep" 20 | label_admin_users: "Beheerders" 21 | label_dynamic_groups: "Dynamische groepen" 22 | label_ldap_attributes_on_a_user: "LDAP-attributen voor een gebruiker" 23 | label_ldap_attributes_on_a_group: "LDAP-attributen voor een groep" 24 | label_log_messages: "Logberichten" 25 | 26 | button_test: "Test" 27 | button_execute: "Uitvoeren" 28 | button_enable: "Inschakelen" 29 | button_disable: "Uitschakelen" 30 | 31 | header_create_groups: "Groepen aanmaken" 32 | header_create_users: "Gebruikers aanmaken" 33 | header_sync_user_fields: "Sync gebruikersvelden" 34 | header_sync_group_fields: "Sync groepsvelden" 35 | 36 | field_nested_groups: "Geneste groepen" 37 | field_create_groups: "Groepen aanmaken" 38 | field_create_users: "Gebruikers aanmaken" 39 | field_sync_on_login: "Synchroniseren bij aanmelden" 40 | field_dyngroups: "Dynamische groepen" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Base-DN voor groepen" 44 | field_group_membership: "Groep-lidmaatschap" 45 | field_class_user: "ObjectClass gebruikers" 46 | field_users_search_scope: "Zoekbereik gebruikers" 47 | field_class_group: "ObjectClass groepen" 48 | field_account_locked_test: "Gebruikersaccount uitgeschakeld test" 49 | 50 | field_groupname_pattern: "Groepsnaam-patroon" 51 | field_group_search_filter: "Zoekfilter groepen" 52 | 53 | field_groupname: "Groepsnaam (groep)" 54 | field_member: "Groepslid (groep)" 55 | field_member_group: "Ledengroepen (groep)" 56 | field_parent_group: "Oudergroepen (groep)" 57 | field_user_memberid: "Groepslid-ID (gebruiker)" 58 | field_group_memberid: "Groepslid-ID (groep)" 59 | field_group_parentid: "Ouder-id (groep)" 60 | field_user_groups: "Groepen (gebruiker)" 61 | field_groupid: "Groeps-id (groep)" 62 | field_account_flags: "Gebruikersaccount vlag (gebruiker)" 63 | field_primary_group: "Hoofdgroep (gebruiker)" 64 | 65 | field_required_group: "Gebruikers moeten lid zijn van" 66 | field_admin_group: "Beheerders-groep" 67 | field_fixed_group: "Gebruikers toevoegen aan groep" 68 | 69 | field_user_group_fields: "Gebruiker/Groepsvelden" 70 | field_firstname: "Voornaam" 71 | field_lastname: "Achternaam" 72 | field_mail: "E-mailadres" 73 | 74 | field_test_users: "Gebruikers" 75 | field_test_groups: "Groepen" 76 | 77 | field_bind_user: "Bind gebruiker" 78 | field_bind_password: "Bind wachtwoord" 79 | 80 | option_users_search_subtree: "Volledige vertakking (subtree)" 81 | option_users_search_onelevel: "Enkel niveau" 82 | 83 | option_group_membership_on_groups: "Van de groepsklasse" 84 | option_group_membership_on_members: "Van de gebruikersklasse" 85 | 86 | option_nested_groups_disabled: "Uitgeschakeld" 87 | option_nested_groups_on_parents: "Lidmaatschap van de ouderklasse" 88 | option_nested_groups_on_members: "Lidmaatschap van de ledenklasse" 89 | 90 | option_dyngroups_disabled: "Uitgeschakeld" 91 | option_dyngroups_enabled: "Ingeschakeld" 92 | option_dyngroups_enabled_with_ttl: "Ingeschakeld met TTL" 93 | 94 | option_sync_on_login_disabled: "Uitgeschakeld" 95 | option_sync_on_login_user_fields: "Gebruikersvelden" 96 | option_sync_on_login_user_fields_and_groups: "Gebruikersvelden en -groepen" 97 | 98 | text_ldap_setting_successfully_updated: "LDAP configuratie is succesvol aangepast." 99 | 100 | field_base_settings: "Basisinstellingen" 101 | option_custom: "Gepersonaliseerd" 102 | 103 | error_cannot_enable_with_invalid_settings: "Synchronisatie kan niet worden ingeschakeld door ongeldige instellingen. Controleer de configuratie-instellingen." 104 | 105 | errors: 106 | messages: 107 | invalid_ldap_attribute: "%{field} heeft een ongeldig LDAP-attribuut" 108 | must_have_ldap_attribute: "%{field} moet een LDAP-attribuut hebben dat kan worden gesynchroniseerd" 109 | invalid_expression: "bevat een ongeldige expressie: %{error_message}" 110 | invalid_regexp: "bevat een ongeldige reguliere expressie: %{error_message}" -------------------------------------------------------------------------------- /config/locales/pl.yml: -------------------------------------------------------------------------------- 1 | pl: 2 | label_ldap_synchronization: "Synchronizacja LDAP" 3 | label_ldap_settings: "Ustawienia LDAP" 4 | label_ldap_servers: "Serwery LDAP" 5 | label_synchronization_actions: "Akcje synchronizacji" 6 | label_synchronize: "Synchronizuj" 7 | label_ldap_attribute: "Atrybuty LDAP" 8 | label_default_value: "Domyślna wartość" 9 | label_test: "Test" 10 | label_result: "Wynik" 11 | label_minutes: "minuty" 12 | 13 | label_not_executed: "Nie uruchomione" 14 | label_no_fields: "Brak pól" 15 | label_not_found: "Nie znaleziono" 16 | label_users_enabled: "Włączeni użytkownicy" 17 | label_a_total_of: "łącznie %{count}" 18 | label_users_locked_by_flag: "Użytkownicy wyłączeni poprzez flagi" 19 | label_users_locked_by_group: "Użytkownicy wyłączeni przez grupy" 20 | label_admin_users: "Administratorzy" 21 | label_dynamic_groups: "Dynamiczne grupy" 22 | label_ldap_attributes_on_a_user: "Atrybuty LDAP użytkownika" 23 | label_ldap_attributes_on_a_group: "Atrybuty LDAP grupy" 24 | label_log_messages: "Wiadomości z Logów" 25 | 26 | button_test: "Test" 27 | button_execute: "Uruchom" 28 | button_enable: "Włącz" 29 | button_disable: "Wyłącz" 30 | 31 | header_create_groups: "Utwórz grupy" 32 | header_create_users: "Utwórz użytkowników" 33 | header_sync_user_fields: "Synchronizuj pola użytkowników" 34 | header_sync_group_fields: "Synchronizuj pola grup" 35 | 36 | field_nested_groups: "Grupy zagnieżdżone" 37 | field_create_groups: "Utwórz grupy" 38 | field_create_users: "Utwórz użytkowników" 39 | field_sync_on_login: "Synchronizuj przy logowaniu" 40 | field_dyngroups: "Dynamiczne grupy" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Bazowy DN grup" 44 | field_group_membership: "Członkowstwo grupy" 45 | field_class_user: "ObjectClass użytkowników" 46 | field_users_search_scope: "Ścieżka szukania użytkowników" 47 | field_class_group: "ObjectClass grup" 48 | field_account_locked_test: "Test na konto wyłączone" 49 | 50 | field_groupname_pattern: "Wzór nazwy grup" 51 | field_group_search_filter: "Filtr szukania grup" 52 | 53 | field_groupname: "Nazwa grupy" 54 | field_member: "Członek (użytkownik)" 55 | field_member_group: "Grupy członka (grupa)" 56 | field_parent_group: "Grupy rodzica (grupa)" 57 | field_user_memberid: "ID członka (użytkownik)" 58 | field_group_memberid: "ID członka grupy" 59 | field_group_parentid: "ID rodzica grupy" 60 | field_user_groups: "Grupy użytkownika" 61 | field_groupid: "ID grupy" 62 | field_account_flags: "Flagi konta użytkownika" 63 | field_primary_group: "Podstawowa grupa użytkownika" 64 | 65 | field_required_group: "Użytkownicy muszą być członkami" 66 | field_admin_group: "Administratorzy grupy" 67 | field_fixed_group: "Dodaj użytkowników do grupy" 68 | 69 | field_user_group_fields: "Pola użytkownik/grupa" 70 | field_firstname: "Imię" 71 | field_lastname: "Nazwisko" 72 | field_mail: "Email" 73 | 74 | field_test_users: "Użytkownicy" 75 | field_test_groups: "Grupy" 76 | field_bind_user: "Binduj użytkownika" 77 | field_bind_password: "Binduj hasło" 78 | 79 | option_users_search_subtree: "Całe drzewo" 80 | option_users_search_onelevel: "Jeden poziom" 81 | 82 | option_group_membership_on_groups: "W klasie grupy" 83 | option_group_membership_on_members: "W klasie użytkownika" 84 | 85 | option_nested_groups_disabled: "Wyłączone" 86 | option_nested_groups_on_parents: "Członkowstwo w klasie nadrzędnej" 87 | option_nested_groups_on_members: "Członkowstwo w klasie członka" 88 | 89 | option_dyngroups_disabled: "Wyłączone" 90 | option_dyngroups_enabled: "Włączone" 91 | option_dyngroups_enabled_with_ttl: "Włączone z TTL" 92 | 93 | option_sync_on_login_disabled: "Wyłączone" 94 | option_sync_on_login_user_fields: "Pola użytkownika" 95 | option_sync_on_login_user_fields_and_groups: "Pola użytkowników i grup" 96 | 97 | text_ldap_setting_successfully_updated: "Konfiguracja LDAP zapisana pomyślnie." 98 | 99 | field_base_settings: "Ustawienia podstawowe" 100 | option_custom: "Dostosowane" 101 | 102 | error_cannot_enable_with_invalid_settings: "Nie można włączyć synchronizacji z nieprawidłowymi ustawieniami. Proszę poprawić konfigurację." 103 | 104 | errors: 105 | messages: 106 | invalid_ldap_attribute: "%{field} posiada nieprawidłowy atrybut LDAP" 107 | must_have_ldap_attribute: "%{field} musi posiadać atrybut LDAP, aby można było synchronizować" 108 | invalid_expression: "zawiera nieprawidłowe wyrażenie: %{error_message}" 109 | invalid_regexp: "zawiera nieprawidłowe wyrażenie regularne: %{error_message}" 110 | -------------------------------------------------------------------------------- /config/locales/pt.yml: -------------------------------------------------------------------------------- 1 | pt: 2 | label_ldap_synchronization: "Syncronização LDAP" 3 | label_ldap_settings: "Definições LDAP" 4 | label_ldap_servers: "Servidores LDAP" 5 | label_synchronization_actions: "Acções de sincronização" 6 | label_synchronize: "Sincronizar" 7 | label_ldap_attribute: "Atributo LDAP" 8 | label_default_value: "Valor por omissão" 9 | label_test: "Teste" 10 | label_result: "Resultado" 11 | label_minutes: "minutos" 12 | 13 | label_not_executed: "Não executado" 14 | label_no_fields: "Sem dados" 15 | label_not_found: "Não encontrado" 16 | label_users_enabled: "Utilizadores activos" 17 | label_a_total_of: "no total de %{count}" 18 | label_users_locked_by_flag: "Utilizadores inactivos por flag" 19 | label_users_locked_by_group: "Utilizadores inactivos por grupo" 20 | label_admin_users: "Administradores redmine" 21 | label_dynamic_grous: "Grupos dinâmicos" 22 | label_ldap_attributes_on_a_user: "Atributos LDAP num utilizador" 23 | label_ldap_attributes_on_a_group: "Atributos LDAP num group" 24 | label_log_messages: "Messagens de log" 25 | 26 | button_test: "Testar" 27 | button_execute: "Executar" 28 | button_enable: "Activar" 29 | button_disable: "Desactivar" 30 | 31 | header_create_groups: "Criar grupos" 32 | header_create_users: "Criar util." 33 | header_sync_user_fields: "Sinc. dados util." 34 | header_sync_group_fields: "Sinc. dados grupos" 35 | 36 | field_nested_groups: "Hierarquia de grupos" 37 | field_create_groups: "Criar grupos" 38 | field_create_users: "Criar utilizadores" 39 | field_sync_on_login: "Sincronizar no login" 40 | field_dyngroups: "Grupos dinâmicos" 41 | field_dyngroups_cache_ttl: "Cache TTL" 42 | 43 | field_groups_base_dn: "Base DN dos grupos" 44 | field_group_membership: "Relação grupo-membro" 45 | field_class_user: "Objectclass de utilizadores" 46 | field_users_search_scope: "Âmbito da pesquisa de utilizadores" 47 | field_class_group: "Objectclass de grupos" 48 | field_account_locked_test: "Teste de conta desactivada" 49 | 50 | field_groupname_pattern: "Filtro regex de grupos" 51 | field_group_search_filter: "Filtro de pesquisa de grupos" 52 | 53 | field_groupname: "Nome do grupo (grupo)" 54 | field_member: "Membros (grupo)" 55 | field_member_group: "Grupos membros (grupo)" 56 | field_parent_group: "Grupos pais (grupo)" 57 | field_user_memberid: "ID do membro (utilizador)" 58 | field_group_memberid: "ID do grupo membro (grupo)" 59 | field_group_parentid: "ID do grupo pai (grupo)" 60 | field_user_groups: "Grupos (utilizador)" 61 | field_groupid: "ID do grupo (grupo)" 62 | field_account_flags: "Flags de controlo (utilizador)" 63 | field_primary_group: "Grupo primário (utilizador)" 64 | 65 | field_required_group: "Bloquear não membros do grupo" 66 | field_admin_group: "Administradores são membros do grupo" 67 | field_fixed_group: "Adicionar novos utilizadores ao grupo" 68 | 69 | field_user_group_fields: "Dados de utilizadores/grupos" 70 | field_firstname: "Nome" 71 | field_lastname: "Apelido" 72 | field_mail: "E-mail" 73 | 74 | field_test_users: "Utilizadores" 75 | field_test_groups: "Grupos" 76 | 77 | option_users_search_subtree: "Toda a subarvore" 78 | option_users_search_onelevel: "Um nível" 79 | 80 | option_group_membership_on_groups: "No grupo" 81 | option_group_membership_on_members: "No utilizador" 82 | 83 | option_nested_groups_disabled: "Desactivada" 84 | option_nested_groups_on_parents: "Relação no grupo pai" 85 | option_nested_groups_on_members: "Relação no grupo membro" 86 | 87 | option_dyngroups_disabled: "Desactivado" 88 | option_dyngroups_enabled: "Activo" 89 | option_dyngroups_enabled_with_ttl: "Activo com um TTL" 90 | 91 | option_sync_on_login_disabled: "Desactivado" 92 | option_sync_on_login_user_fields: "Dados dos utilizadores" 93 | option_sync_on_login_user_fields_and_groups: "Dados e grupos dos utilizadores" 94 | 95 | text_ldap_setting_successfully_updated: "Definições LDAP actualizadas com sucesso." 96 | 97 | field_base_settings: "Configuração base" 98 | option_custom: "Personalizado" 99 | 100 | error_cannot_enable_with_invalid_settings: "Não é possivel activar a sincronização enquanto houverem erros na configuração. Deverá rever a configuração." 101 | 102 | errors: 103 | messages: 104 | invalid_ldap_attribute: "%{value} tem um atributo LDAP inválido" 105 | must_have_ldap_attribute: "%{value} requere um atributo LDAP para ser sincronizado" 106 | invalid_expression: "contém uma expressão não válida: %{error_message}" 107 | invalid_regexp: "contém uma expressão regular não válida: %{error_message}" -------------------------------------------------------------------------------- /config/locales/ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | label_ldap_synchronization: "Синхронизация с LDAP" 3 | label_ldap_settings: "Настройки LDAP" 4 | label_ldap_servers: "Серверы LDAP" 5 | label_synchronization_actions: "Действия синхронизации" 6 | label_synchronize: "Синхронизировать" 7 | label_ldap_attribute: "Атрибут LDAP" 8 | label_default_value: "Значение по умолчанию" 9 | label_test: "Проверка" 10 | label_result: "Результат" 11 | label_minutes: "минут" 12 | 13 | label_not_executed: "Не выполнялась" 14 | label_no_fields: "Нет полей" 15 | label_not_found: "Не найден" 16 | label_users_enabled: "пользователей разблокировано" 17 | label_a_total_of: "Всего %{count}" 18 | label_users_locked_by_flag: "пользователей заблокировано по флагу" 19 | label_users_locked_by_group: "пользователей заблокировано по группе" 20 | label_admin_users: "Администраторы" 21 | label_dynamic_groups: "Динамические группы" 22 | label_ldap_attributes_on_a_user: "Атрибуты LDAP пользователя" 23 | label_ldap_attributes_on_a_group: "Атрибуты LDAP группы" 24 | label_log_messages: "Сообщения журнала" 25 | 26 | button_test: "Проверка" 27 | button_execute: "Выполнить" 28 | button_enable: "Включить" 29 | button_disable: "Выключить" 30 | 31 | header_create_groups: "Создание групп" 32 | header_create_users: "Создание пользователей" 33 | header_sync_user_fields: "Синх. пользователей" 34 | header_sync_group_fields: "Синх. группы" 35 | 36 | field_nested_groups: "Вложенные группы" 37 | field_create_groups: "Создавать группы" 38 | field_create_users: "Создавать пользователей" 39 | field_sync_on_login: "Синхронизировать при входе" 40 | field_dyngroups: "Динамические группы" 41 | field_dyngroups_cache_ttl: "TTL кеша" 42 | 43 | field_groups_base_dn: "Базовый DN для групп" 44 | field_group_membership: "Членство в группах" 45 | field_class_user: "objectclass пользователей" 46 | field_users_search_scope: "Users search scope" 47 | field_class_group: "objectclass групп" 48 | field_account_locked_test: "Проверка заблокированности учетной записи" 49 | 50 | field_groupname_pattern: "Шаблон имени группы" 51 | field_group_search_filter: "Фильтр поиска групп" 52 | 53 | field_groupname: "Название группы (группа)" 54 | field_member: "Подчиненные пользователи (группа)" 55 | field_member_group: "Подчиненные группы (группа)" 56 | field_parent_group: "Родительские группы (группа)" 57 | field_user_memberid: "id подчиненного (пользователь)" 58 | field_group_memberid: "id подчиненного (группа)" 59 | field_group_parentid: "id родителя (группа)" 60 | field_user_groups: "Группы (пользователь)" 61 | field_groupid: "id группы (группа)" 62 | field_account_flags: "Флаги учетной записи (пользователь)" 63 | field_primary_group: "Основная группа (пользователь)" 64 | 65 | field_required_group: "Пользователи должны входить в группу" 66 | field_admin_group: "Группа администраторов" 67 | field_fixed_group: "Добавлять пользователей в группы" 68 | field_group_prefix: "Добавлять префикс к имени группы" 69 | 70 | field_user_group_fields: "Поля пользователя/группы" 71 | field_firstname: "Имя" 72 | field_lastname: "Фамилия" 73 | field_mail: "Email" 74 | 75 | field_test_users: "Пользователи" 76 | field_test_groups: "Группы" 77 | 78 | option_users_search_subtree: "Whole subtree" 79 | option_users_search_onelevel: "One level" 80 | 81 | option_group_membership_on_groups: "Список пользователей содержится в группе " 82 | option_group_membership_on_members: "Список групп содержится в пользователе" 83 | 84 | option_nested_groups_disabled: "Выключены" 85 | option_nested_groups_on_parents: "Список подчиненных групп содержится в родительской группе" 86 | option_nested_groups_on_members: "Список родительских групп содержится в подчиненной группе" 87 | 88 | option_dyngroups_disabled: "Выключены" 89 | option_dyngroups_enabled: "Включены" 90 | option_dyngroups_enabled_with_ttl: "Включены с TTL" 91 | 92 | option_sync_on_login_disabled: "Ничего" 93 | option_sync_on_login_user_fields: "Данные пользователя" 94 | option_sync_on_login_user_fields_and_groups: "Данные и группы пользователя" 95 | 96 | text_ldap_setting_successfully_updated: "Конфигурация Ldap успешно обновлена." 97 | 98 | field_base_settings: "Базовые настройки" 99 | option_custom: "Вручную" 100 | 101 | error_cannot_enable_with_invalid_settings: "Нельзя включить синхронизацию с неправильными настройками. Пожалуйста проверьте настройки." 102 | 103 | errors: 104 | messages: 105 | invalid_ldap_attribute: "Поле '%{field}' имеет неправильный атрибут LDAP" 106 | must_have_ldap_attribute: "Для синхронизации поле '%{field}' должно иметь атрибут LDAP" 107 | invalid_expression: "содержит неправильное выражение: %{error_message}" 108 | invalid_regexp: "содержит неправильное регулярное выражение: %{error_message}" 109 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | resources :ldap_settings, :path => 'admin/ldap_sync', :only => [:show, :edit, :update, :index] do 19 | member do 20 | put 'test' 21 | put 'disable' 22 | put 'enable' 23 | end 24 | get 'base_settings', :constraints => { :format => /js/ }, :on => :collection 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/201108021245_change_settings_name.rb: -------------------------------------------------------------------------------- 1 | class ChangeSettingsName < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:add_to_group] = settings.delete(:domain_group) 12 | settings[:groupname_pattern] = settings.delete(:groupname_filter) 13 | settings[:create_groups] = true 14 | settings[:create_users] = true 15 | settings[:sync_user_attributes] = false 16 | settings[:attr_member] = 'member' 17 | settings[:class_group] = 'group' 18 | settings[:class_user] = 'user' 19 | Setting.plugin_redmine_ldap_sync = all_settings 20 | end if settings 21 | end 22 | end 23 | 24 | def self.down 25 | # Nothing to do here 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/201110050735_add_user_memberid_setting.rb: -------------------------------------------------------------------------------- 1 | class AddUserMemberidSetting < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:attr_user_memberid] = 'dn' 12 | Setting.plugin_redmine_ldap_sync = all_settings 13 | end if settings 14 | end 15 | end 16 | 17 | def self.down 18 | # Nothing to do here 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/201111271700_add_group_membership_setting.rb: -------------------------------------------------------------------------------- 1 | class AddGroupMembershipSetting < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:group_membership] = 'on_groups' 12 | settings[:attr_user_groups] = 'memberof' 13 | settings[:attr_groupid] = 'distinguishedName' 14 | Setting.plugin_redmine_ldap_sync = all_settings 15 | end if settings 16 | end 17 | end 18 | 19 | def self.down 20 | # Nothing to do here 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/201201010043_create_ldap_cache_dir.rb: -------------------------------------------------------------------------------- 1 | class CreateLdapCacheDir < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | cache_dir = Rails.root.join("tmp/ldap_cache") 5 | say_with_time "Creating path '#{cache_dir}'" do 6 | FileUtils.mkdir_p cache_dir 7 | end 8 | end 9 | 10 | def self.down 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/201201071359_update_attributes_to_sync.rb: -------------------------------------------------------------------------------- 1 | class UpdateAttributesToSync < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings.delete(:sync_user_attributes) 12 | settings[:user_fields_to_sync] = settings[:attributes_to_sync] 13 | settings.delete(:attributes_to_sync) 14 | Setting.plugin_redmine_ldap_sync = all_settings 15 | end if settings 16 | end 17 | end 18 | 19 | def self.down 20 | # nothing to do 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/201201291950_rename_must_be_member_of_and_add_to_group_settings.rb: -------------------------------------------------------------------------------- 1 | class RenameMustBeMemberOfAndAddToGroupSettings < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:required_group] = settings[:must_be_member_of] 12 | settings[:fixed_group] = settings[:add_to_group] 13 | Setting.plugin_redmine_ldap_sync = all_settings 14 | end if settings 15 | end 16 | end 17 | 18 | def self.down 19 | all_settings = Setting.plugin_redmine_ldap_sync 20 | return unless all_settings 21 | 22 | AuthSourceLdap.all.each do |as| 23 | settings = all_settings[as.name] 24 | 25 | say_with_time "Updating settings for '#{as.name}'" do 26 | settings[:must_be_member_of] = settings[:required_group] 27 | settings[:add_to_group] = settings[:fixed_group] 28 | Setting.plugin_redmine_ldap_sync = all_settings 29 | end if settings 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /db/migrate/201201302250_remove_attr_prefix_settings.rb: -------------------------------------------------------------------------------- 1 | class RemoveAttrPrefixSettings < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:groupname] = settings[:attr_groupname] 12 | settings[:member] = settings[:attr_member] 13 | settings[:user_memberid] = settings[:attr_user_memberid] 14 | settings[:user_groups] = settings[:attr_user_groups] 15 | settings[:groupid] = settings[:attr_groupid] 16 | settings[:member_group] = settings[:attr_member_group] 17 | settings[:goup_memberid] = settings[:attr_group_memberid] 18 | Setting.plugin_redmine_ldap_sync = all_settings 19 | end if settings 20 | end 21 | end 22 | 23 | def self.down 24 | all_settings = Setting.plugin_redmine_ldap_sync 25 | return unless all_settings 26 | 27 | AuthSourceLdap.all.each do |as| 28 | settings = all_settings[as.name] 29 | 30 | say_with_time "Updating settings for '#{as.name}'" do 31 | settings[:attr_groupname] = settings[:groupname] 32 | settings[:attr_member] = settings[:member] 33 | settings[:attr_user_memberid] = settings[:user_memberid] 34 | settings[:attr_user_groups] = settings[:user_groups] 35 | settings[:attr_groupid]= settings[:groupid] 36 | settings[:attr_member_group] = settings[:member_group] 37 | settings[:attr_group_memberid] = settings[:goup_memberid] 38 | Setting.plugin_redmine_ldap_sync = all_settings 39 | end if settings 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/201202082153_add_account_flags_setting.rb: -------------------------------------------------------------------------------- 1 | class AddAccountFlagsSetting < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:account_flags] = 'userAccountControl' 12 | settings[:account_disabled_test] = 'flags.to_i & 2 != 0' 13 | Setting.plugin_redmine_ldap_sync = all_settings 14 | end if settings 15 | end 16 | end 17 | 18 | def self.down 19 | # nothing to do 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /db/migrate/201211202050_update_check_box_values.rb: -------------------------------------------------------------------------------- 1 | class UpdateCheckBoxValues < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:active] = (['yes', '1'].include?(settings[:active])? '1': '0') 12 | settings[:create_groups] = (['yes', '1'].include?(settings[:create_groups])? '1': '0') 13 | settings[:create_users] = (['yes', '1'].include?(settings[:create_users])? '1': '0') 14 | settings[:sync_user_attributes] = (['yes', '1'].include?(settings[:sync_user_attributes])? '1': '0') 15 | Setting.plugin_redmine_ldap_sync = all_settings 16 | end if settings 17 | end 18 | end 19 | 20 | def self.down 21 | # nothing to do 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /db/migrate/201302052050_update_user_group_fields.rb: -------------------------------------------------------------------------------- 1 | class UpdateUserGroupFields < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:group_fields_to_sync] ||= [] 12 | settings[:user_fields_to_sync] ||= [] 13 | settings[:user_ldap_attrs] ||= {} 14 | settings[:group_ldap_attrs] ||= {} 15 | Setting.plugin_redmine_ldap_sync = all_settings 16 | end if settings 17 | end 18 | end 19 | 20 | def self.down 21 | # nothing to do 22 | end 23 | end -------------------------------------------------------------------------------- /db/migrate/201302202301_change_setting_id_from_name_to_auth_source_id.rb: -------------------------------------------------------------------------------- 1 | class ChangeSettingIdFromNameToAuthSourceId < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.name] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | all_settings[as.id] = settings 12 | all_settings.delete as.name 13 | 14 | Setting.plugin_redmine_ldap_sync = all_settings 15 | end if settings 16 | end 17 | end 18 | 19 | def self.down 20 | all_settings = Setting.plugin_redmine_ldap_sync 21 | return unless all_settings 22 | 23 | AuthSourceLdap.all.each do |as| 24 | settings = all_settings[as.id] 25 | 26 | say_with_time "Updating settings for '#{as.name}'" do 27 | all_settings[as.name] = settings 28 | all_settings.delete as.id 29 | 30 | Setting.plugin_redmine_ldap_sync = all_settings 31 | end if settings 32 | end 33 | end 34 | end -------------------------------------------------------------------------------- /db/migrate/201302212308_enable_sync_on_login.rb: -------------------------------------------------------------------------------- 1 | class EnableSyncOnLogin < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.id] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:sync_on_login] = 'user_fields_and_groups' 12 | 13 | Setting.plugin_redmine_ldap_sync = all_settings 14 | end if settings 15 | end 16 | end 17 | 18 | def self.down 19 | # nothing to do 20 | end 21 | end -------------------------------------------------------------------------------- /db/migrate/201503252355_add_users_search_scope.rb: -------------------------------------------------------------------------------- 1 | class AddUsersSearchScope < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | all_settings = Setting.plugin_redmine_ldap_sync 5 | return unless all_settings 6 | 7 | AuthSourceLdap.all.each do |as| 8 | settings = all_settings[as.id] 9 | 10 | say_with_time "Updating settings for '#{as.name}'" do 11 | settings[:users_search_scope] = 'subtree' 12 | 13 | Setting.plugin_redmine_ldap_sync = all_settings 14 | end if settings 15 | end 16 | end 17 | 18 | def self.down 19 | # nothing to do 20 | end 21 | 22 | end -------------------------------------------------------------------------------- /db/migrate/20170524063056_rename_account_disabled_test.rb: -------------------------------------------------------------------------------- 1 | class RenameAccountDisabledTest < ActiveRecord::Migration[4.2] 2 | def self.up 3 | all_settings = Setting.plugin_redmine_ldap_sync 4 | return unless all_settings 5 | 6 | AuthSourceLdap.all.each do |as| 7 | settings = all_settings[as.id] 8 | 9 | say_with_time "Updating settings for '#{as.name}'" do 10 | settings[:account_locked_test] = settings[:account_disabled_test] 11 | settings.delete(:account_disabled_test) 12 | Setting.plugin_redmine_ldap_sync = all_settings 13 | end if settings 14 | end 15 | end 16 | 17 | def self.down 18 | all_settings = Setting.plugin_redmine_ldap_sync 19 | return unless all_settings 20 | 21 | AuthSourceLdap.all.each do |as| 22 | settings = all_settings[as.id] 23 | 24 | say_with_time "Updating settings for '#{as.name}'" do 25 | settings[:account_disabled_test] = settings[:account_locked_test] 26 | settings.delete(:account_locked_test) 27 | Setting.plugin_redmine_ldap_sync = all_settings 28 | end if settings 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /doc/RUNNING_TESTS: -------------------------------------------------------------------------------- 1 | Running the tests 2 | ================= 3 | 4 | Run `NAME=redmine_ldap_sync rake redmine:plugins:test` to execute all 5 | the tests. 6 | 7 | 8 | Creating a test ldap database 9 | ============================= 10 | 11 | Install slapd and make sure the server can be reached at 127.0.0.1 on port 389. 12 | 13 | Initialize the config database with: 14 | `slaptest -f redmine_ldap_sync/test/fixtures/ldap/slapd.conf -F /etc/ldap/slapd.d/` 15 | `chown -R openldap:openldap /etc/ldap/slapd.d /var/lib/ldap` 16 | 17 | Restart slapd and load the sample data with: 18 | `ldapadd -Dcn=admin,dc=redmine,dc=org -w password -f redmine_ldap_sync/test/fixtures/ldap/test-ldap.ldif -c` 19 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | require 'redmine' 2 | 3 | Redmine::Plugin.register :redmine_ldap_sync do 4 | name 'Redmine LDAP Sync' 5 | author 'Ricardo Santos, Taine Woo' 6 | author_url 'https://github.com/tainewoo' 7 | description 'Syncs users and groups with ldap' 8 | url 'https://github.com/tainewoo/redmine_ldap_sync' 9 | version '2.2.0' 10 | requires_redmine :version_or_higher => '2.1.0' 11 | 12 | settings :default => HashWithIndifferentAccess.new() 13 | menu :admin_menu, :ldap_sync, { :controller => 'ldap_settings', :action => 'index' }, :caption => :label_ldap_synchronization, 14 | :html => {:class => 'icon icon-ldap-sync'} 15 | end 16 | 17 | #RedmineApp::Application.config.after_initialize do 18 | Rails.application.config.to_prepare do 19 | require_dependency 'ldap_sync/core_ext' 20 | require_dependency 'ldap_sync/infectors' 21 | end 22 | 23 | # hooks 24 | require_dependency 'ldap_sync/hooks' 25 | -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) } -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/ber.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | if ('0.12.0'..'0.13.0') === Gem.loaded_specs['net-ldap'].version.to_s 19 | require 'net/ber' 20 | 21 | ## 22 | # A String object with a BER identifier attached. 23 | # 24 | class Net::BER::BerIdentifiedString < String 25 | attr_accessor :ber_identifier 26 | 27 | # The binary data provided when parsing the result of the LDAP search 28 | # has the encoding 'ASCII-8BIT' (which is basically 'BINARY', or 'unknown'). 29 | # 30 | # This is the kind of a backtrace showing how the binary `data` comes to 31 | # BerIdentifiedString.new(data): 32 | # 33 | # @conn.read_ber(syntax) 34 | # -> StringIO.new(self).read_ber(syntax), i.e. included from module 35 | # -> Net::BER::BERParser.read_ber(syntax) 36 | # -> (private)Net::BER::BERParser.parse_ber_object(syntax, id, data) 37 | # 38 | # In the `#parse_ber_object` method `data`, according to its OID, is being 39 | # 'casted' to one of the Net::BER:BerIdentifiedXXX classes. 40 | # 41 | # As we are using LDAP v3 we can safely assume that the data is encoded 42 | # in UTF-8 and therefore the only thing to be done when instantiating is to 43 | # switch the encoding from 'ASCII-8BIT' to 'UTF-8'. 44 | # 45 | # Unfortunately, there are some ActiveDirectory specific attributes 46 | # (like `objectguid`) that should remain binary (do they really?). 47 | # Using the `#valid_encoding?` we can trap this cases. Special cases like 48 | # Japanese, Korean, etc. encodings might also profit from this. However 49 | # I have no clue how this encodings function. 50 | def initialize args 51 | super 52 | # 53 | # Check the encoding of the newly created String and set the encoding 54 | # to 'UTF-8' (NOTE: we do NOT change the bytes, but only set the 55 | # encoding to 'UTF-8'). 56 | current_encoding = encoding 57 | if current_encoding == Encoding::BINARY 58 | force_encoding('UTF-8') 59 | force_encoding(current_encoding) unless valid_encoding? 60 | end 61 | end 62 | end 63 | end -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/file_store.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | class ActiveSupport::Cache::FileStore 19 | def delete_unless 20 | options = merged_options(options) 21 | search_dir(cache_path) do |path| 22 | key = file_path_key(path) 23 | delete_entry(key, options) unless yield(key) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/ldap.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require 'net/ldap' 19 | 20 | class Net::LDAP 21 | if Gem.loaded_specs['net-ldap'].version < Gem::Version.new('0.12.0') 22 | Error = LdapError 23 | end 24 | end -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/ldap_entry.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require 'net/ldap' 19 | 20 | class Net::LDAP 21 | class Entry 22 | include Enumerable 23 | end 24 | end -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/migration.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | class ActiveRecord::Migration 19 | unless defined? self.[] 20 | 21 | # Enables the use of versioned migrations on rails < 5 22 | def self.[](version) 23 | self 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /lib/ldap_sync/core_ext/string.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require 'net/ldap' 19 | 20 | module Net::BER::Extensions::String 21 | if Gem.loaded_specs['net-ldap'].version < Gem::Version.new('0.12.0') 22 | def raw_utf8_encoded 23 | if self.respond_to?(:encode) && self.encoding.name != 'ASCII-8BIT' 24 | self.encode('UTF-8').force_encoding('ASCII-8BIT') 25 | else 26 | self 27 | end 28 | end 29 | end 30 | end -------------------------------------------------------------------------------- /lib/ldap_sync/dry_run/group.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSync::DryRun::Group 19 | 20 | module InstanceMethods 21 | def find_or_create_by_lastname(lastname, attributes = {}) 22 | group = find_by_lastname(lastname) 23 | return group if group.present? 24 | 25 | group = ::Group.new(attributes.merge(:lastname => lastname)) 26 | puts " !! New group '#{lastname}'" if (group.valid?) 27 | 28 | group 29 | end 30 | end 31 | 32 | def self.included(receiver) 33 | receiver.send(:include, InstanceMethods) 34 | 35 | receiver.instance_eval do 36 | has_and_belongs_to_many :users do 37 | def <<(users) 38 | puts " !! Added to group '#{proxy_association.owner.lastname}'" 39 | end 40 | end 41 | end 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /lib/ldap_sync/dry_run/user.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSync::DryRun::User 19 | 20 | module ClassMethods 21 | def create(attributes) 22 | user = User.new(attributes) 23 | yield user if block_given? 24 | user 25 | end 26 | end 27 | 28 | module InstanceMethods 29 | def lock!();end 30 | 31 | def activate!(); end 32 | 33 | def update_attributes(attrs = {}); end 34 | 35 | def save(*args); end 36 | end 37 | 38 | def self.included(receiver) 39 | receiver.extend(ClassMethods) 40 | receiver.send(:include, InstanceMethods) 41 | 42 | receiver.instance_eval do 43 | has_and_belongs_to_many :groups do 44 | def <<(groups) 45 | puts " !! Added to groups '#{groups.map(&:lastname).join("', '")}'" unless groups.empty? 46 | end 47 | 48 | def delete(*groups) 49 | puts " !! Removed from groups '#{groups.map(&:lastname).join("', '")}'" unless groups.empty? 50 | end 51 | end 52 | 53 | remove_method :lock!, :activate! 54 | end 55 | 56 | end 57 | end -------------------------------------------------------------------------------- /lib/ldap_sync/hooks.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSync 19 | class Hooks < Redmine::Hook::ViewListener 20 | 21 | # Add a question CSS class 22 | def view_layouts_base_html_head(context = { }) 23 | stylesheet_link_tag 'ldap_sync.css', :plugin => 'redmine_ldap_sync' 24 | end 25 | 26 | end 27 | end -------------------------------------------------------------------------------- /lib/ldap_sync/infectors.rb: -------------------------------------------------------------------------------- 1 | module LdapSync::Infectors 2 | Dir[File.join(File.dirname(__FILE__), "infectors", "*.rb")].each do |file| 3 | require_dependency file; 4 | infected_name = File.basename(file, ".rb").classify 5 | _module = const_get(infected_name) 6 | _class = Kernel.const_get(infected_name) 7 | _class.send(:include, _module) unless _class.included_modules.include? _module 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/ldap_sync/infectors/group.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSync::Infectors::Group 19 | 20 | module InstanceMethods 21 | def set_default_values 22 | custom_fields = GroupCustomField.where("default_value is not null") 23 | 24 | self.custom_field_values = custom_fields.each_with_object({}) do |f, h| 25 | h[f.id] = f.default_value 26 | end 27 | end 28 | 29 | def synced_fields=(attrs) 30 | self.custom_field_values = attrs 31 | end 32 | end 33 | 34 | def self.included(receiver) 35 | receiver.send(:include, InstanceMethods) 36 | end 37 | 38 | end -------------------------------------------------------------------------------- /lib/ldap_sync/infectors/user.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | module LdapSync::Infectors::User 19 | #::User::STANDARD_FIELDS = %w( firstname lastname mail ) 20 | 21 | module InstanceMethods 22 | def add_to_fixed_group 23 | return unless auth_source.try :has_fixed_group? 24 | 25 | self.groups << ::Group.where(:lastname => auth_source.fixed_group).first_or_create 26 | end 27 | 28 | def sync_fields_and_groups 29 | return unless sync_on_create? 30 | 31 | auth_source.sync_user(self, false, :login => login, :password => password, :try_to_login => true) 32 | end 33 | 34 | def set_default_values 35 | custom_fields = UserCustomField.where("default_value is not null") 36 | self.custom_field_values = custom_fields.each_with_object({}) do |f, h| 37 | h[f.id] = f.default_value 38 | end 39 | 40 | self.language = Setting.default_language 41 | self.mail_notification = Setting.default_notification_option 42 | end 43 | 44 | def synced_fields=(attrs) 45 | self.attributes = attrs.slice(*::User::STANDARD_FIELDS) 46 | self.custom_field_values = attrs.except(*::User::STANDARD_FIELDS) 47 | end 48 | 49 | def member_of_group?(groupname) 50 | self.groups.exists?(:lastname => groupname) 51 | end 52 | 53 | def set_admin! 54 | self.update_attribute(:admin, true) 55 | end 56 | 57 | def unset_admin! 58 | self.update_attribute(:admin, false) 59 | end 60 | 61 | def archive! 62 | self.groups.destroy_all 63 | self.memberships.each {|m| m.member_roles.destroy_all} 64 | self.lock! 65 | end 66 | 67 | def sync_on_create!; @sync_on_create = true; end 68 | def sync_on_create?; @sync_on_create == true; end 69 | 70 | # Compatibility with redmine 2.x 71 | def email_is_taken 72 | if respond_to?(:email_address) 73 | # Redmine > 3.x 74 | email_address.errors.added? :address, :taken 75 | else 76 | # Redmine < 3.x 77 | errors.added? :mail, :taken 78 | end 79 | end 80 | end 81 | 82 | module ClassMethods 83 | def try_to_login_with_ldap_sync(*args) 84 | user = try_to_login_without_ldap_sync(*args) 85 | return user unless user.try(:sync_on_login?) 86 | 87 | login, password = *args 88 | if user.new_record? 89 | user.sync_on_create! 90 | user unless user.auth_source.locked_on_ldap?(user, 91 | :login => login, 92 | :password => password) 93 | else 94 | user.auth_source.sync_user(user, false, :login => login, :password => password, :try_to_login => true) 95 | user if user.active? 96 | end 97 | rescue => text 98 | raise text 99 | end 100 | end 101 | 102 | def self.included(receiver) 103 | receiver.extend(ClassMethods) 104 | receiver.send(:include, InstanceMethods) 105 | 106 | receiver.instance_eval do 107 | after_create :add_to_fixed_group, :sync_fields_and_groups 108 | delegate :sync_on_login?, :to => :auth_source, :allow_nil => true 109 | end 110 | receiver.class_eval do 111 | class << self 112 | alias_method :try_to_login_without_ldap_sync, :try_to_login 113 | alias_method :try_to_login, :try_to_login_with_ldap_sync 114 | end 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /lib/tasks/ldap_sync.rake: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | namespace :redmine do 19 | namespace :plugins do 20 | namespace :ldap_sync do 21 | 22 | desc "Synchronize redmine's users fields and groups with those on LDAP" 23 | task :sync_users => :environment do |t, args| 24 | init_task 25 | 26 | AuthSourceLdap.activate_users! unless ENV['ACTIVATE_USERS'].nil? 27 | AuthSourceLdap.all.each do |as| 28 | trace "Synchronizing '#{as.name}' users..." 29 | as.sync_users 30 | end 31 | end 32 | 33 | desc "Synchronize redmine's groups fields with those on LDAP" 34 | task :sync_groups => :environment do |t, args| 35 | init_task 36 | 37 | AuthSourceLdap.all.each do |as| 38 | trace "Synchronizing '#{as.name}' groups..." 39 | as.sync_groups 40 | end 41 | end 42 | 43 | desc "Synchronize both redmine's users and groups with LDAP" 44 | task :sync_all => [:sync_groups, :sync_users] 45 | 46 | def init_task 47 | AuthSourceLdap.running_rake! 48 | 49 | if defined?(ActiveRecord::Base) 50 | ActiveRecord::Base.logger = Logger.new(STDOUT) 51 | ActiveRecord::Base.logger.level = Logger::WARN 52 | end 53 | 54 | if %w(debug error change silent).include? ENV['LOG_LEVEL'] 55 | AuthSourceLdap.trace_level = ENV['LOG_LEVEL'].to_sym 56 | end 57 | 58 | unless ENV['DRY_RUN'].nil? 59 | trace "\n!!! Dry-run execution !!!\n" 60 | 61 | User.send :include, LdapSync::DryRun::User 62 | Group.send :include, LdapSync::DryRun::Group 63 | end 64 | end 65 | end 66 | 67 | def trace(msg) 68 | return if [:silent, :error, :change].include?(AuthSourceLdap.trace_level) 69 | 70 | puts msg 71 | end 72 | 73 | namespace :redmine_ldap_sync do 74 | task :sync_users => 'redmine:plugins:ldap_sync:sync_users' 75 | end 76 | end 77 | end -------------------------------------------------------------------------------- /lib/tasks/testing.rake: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require 'rake/testtask' 19 | 20 | namespace :redmine do 21 | namespace :plugins do 22 | namespace :ldap_sync do 23 | LDAP_SYNC='redmine_ldap_sync' 24 | 25 | desc 'Runs the ldap_sync tests.' 26 | task :test do 27 | require 'redmine/version' 28 | Rake::Task["redmine:plugins:ldap_sync:test:units"].invoke 29 | Rake::Task["redmine:plugins:ldap_sync:test:functionals"].invoke 30 | Rake::Task["redmine:plugins:ldap_sync:test:integration"].invoke 31 | 32 | if RUBY_VERSION >= '1.9.3' && Redmine::VERSION.to_s >= '2.3.0' 33 | Rake::Task["redmine:plugins:ldap_sync:test:ui"].invoke 34 | end 35 | end 36 | 37 | namespace :test do 38 | desc 'Runs the plugins ui tests.' 39 | Rake::TestTask.new :ui => "db:test:prepare" do |t| 40 | t.libs << "test" 41 | t.verbose = true 42 | t.pattern = "plugins/#{LDAP_SYNC}/test/ui/**/*_test.rb" 43 | end 44 | 45 | desc 'Runs the plugins unit tests.' 46 | Rake::TestTask.new :units => "db:test:prepare" do |t| 47 | t.libs << "test" 48 | t.verbose = true 49 | t.pattern = "plugins/#{LDAP_SYNC}/test/unit/**/*_test.rb" 50 | end 51 | 52 | desc 'Runs the plugins functional tests.' 53 | Rake::TestTask.new :functionals => "db:test:prepare" do |t| 54 | t.libs << "test" 55 | t.verbose = true 56 | t.pattern = "plugins/#{LDAP_SYNC}/test/functional/**/*_test.rb" 57 | end 58 | 59 | desc 'Runs the plugins integration tests.' 60 | Rake::TestTask.new :integration => "db:test:prepare" do |t| 61 | t.libs << "test" 62 | t.verbose = true 63 | t.pattern = "plugins/#{LDAP_SYNC}/test/integration/**/*_test.rb" 64 | end 65 | end 66 | 67 | namespace :coveralls do 68 | desc "Push latest coverage results to Coveralls.io" 69 | task :test => 'redmine:plugins:ldap_sync:test' do 70 | require 'simplecov' 71 | ::SimpleCov.root Rails.root.join('plugins', "#{LDAP_SYNC}") 72 | 73 | require 'coveralls' 74 | Coveralls.push! 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /script/ci.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | set -e # exit if any command fails 3 | 4 | setenv() { 5 | export RAILS_ENV=test 6 | export RUBYOPT=-W1 7 | export IN_RBL_TESTENV=true 8 | export PATH_TO_LDAPSYNC=$(pwd) 9 | export RUBY_VERSION=$(ruby -e 'print RUBY_VERSION') 10 | if [[ -z "$REDMINE" ]]; then 11 | echo "You have not set REDMINE" 12 | exit 1 13 | fi 14 | if [ "$VERBOSE" = "yes" ]; then export TRACE=--trace; fi 15 | if [ ! "$VERBOSE" = "yes" ]; then export QUIET=--quiet; fi 16 | 17 | case $REDMINE in 18 | 2.*.*) export PATH_TO_PLUGINS=./plugins # for redmine 2.x.x 19 | export REDMINE_TARBALL=https://github.com/edavis10/redmine/archive/$REDMINE.tar.gz 20 | ;; 21 | *.*-stable) export PATH_TO_PLUGINS=./plugins # for redmine 2.x-stable 22 | export REDMINE_SVN_REPO=http://svn.redmine.org/redmine/branches/$REDMINE 23 | ;; 24 | master) export PATH_TO_PLUGINS=./plugins 25 | export REDMINE_SVN_REPO=http://svn.redmine.org/redmine/trunk/ 26 | ;; 27 | *) echo "Unsupported platform $REDMINE" 28 | exit 1 29 | ;; 30 | esac 31 | } 32 | 33 | extract_args() { 34 | while :; do 35 | case "$1" in 36 | --target) export TARGET="$2"; shift; shift;; 37 | -*) echo "Invalid argument $1"; exit 2;; 38 | *) break;; 39 | esac 40 | done 41 | } 42 | 43 | trace() { 44 | if [ "$VERBOSE" = "yes" ]; then echo $@; fi 45 | } 46 | 47 | clone_redmine() 48 | { 49 | setenv; extract_args $@ 50 | 51 | if [[ -z "$TARGET" ]]; then 52 | echo "You have not set a target directory"; exit 1 53 | fi 54 | 55 | rm -rf $TARGET 56 | if [ -n "${REDMINE_GIT_REPO}" ]; then 57 | git clone -b $REDMINE_GIT_TAG --depth=100 $QUIET $REDMINE_GIT_REPO $TARGET 58 | pushd $TARGET 1> /dev/null 59 | git checkout $REDMINE_GIT_TAG 60 | popd 1> /dev/null 61 | elif [ -n "${REDMINE_HG_REPO}" ]; then 62 | hg clone -r $REDMINE_HG_TAG $QUIET $REDMINE_HG_REPO $TARGET 63 | elif [ -n "${REDMINE_SVN_REPO}" ]; then 64 | svn co $QUIET $REDMINE_SVN_REPO $TARGET 65 | else 66 | mkdir -p $TARGET 67 | wget $REDMINE_TARBALL -O- | tar -C $TARGET -xz --strip=1 --show-transformed -f - 68 | fi 69 | } 70 | 71 | install_plugin_gemfile() 72 | { 73 | setenv 74 | 75 | mkdir $REDMINE_DIR/$PATH_TO_PLUGINS/redmine_ldap_sync 76 | ln -s "$PATH_TO_LDAPSYNC/config/Gemfile.travis" "$REDMINE_DIR/$PATH_TO_PLUGINS/redmine_ldap_sync/Gemfile" 77 | 78 | if [ "$RUBY_VERSION" == "1.8.7" ]; then 79 | sed -i.bak '/test-unit/d' "$REDMINE_DIR/Gemfile" 80 | fi 81 | } 82 | 83 | prepare_redmine() 84 | { 85 | setenv 86 | 87 | pushd $REDMINE_DIR 1> /dev/null 88 | 89 | trace 'Database migrations' 90 | bundle exec rake db:migrate $TRACE 91 | 92 | trace 'Load defaults' 93 | bundle exec rake redmine:load_default_data REDMINE_LANG=en $TRACE 94 | 95 | trace 'Session token' 96 | bundle exec rake generate_secret_token $TRACE 97 | 98 | popd 1> /dev/null 99 | } 100 | 101 | prepare_plugin() 102 | { 103 | setenv 104 | 105 | pushd $REDMINE_DIR 1> /dev/null 106 | 107 | ln -s $PATH_TO_LDAPSYNC/* $PATH_TO_PLUGINS/redmine_ldap_sync 108 | 109 | trace 'Prepare plugins' 110 | bundle exec rake redmine:plugins NAME=redmine_ldap_sync $TRACE 111 | 112 | popd 1> /dev/null 113 | } 114 | 115 | start_ldap() 116 | { 117 | export LDAPNOINIT=yes 118 | 119 | LDAPBASE=$(mktemp --tmpdir=/tmp -d ldapsyncldap.XXXXX) 120 | LDAPCONF=test/fixtures/ldap 121 | 122 | if [ -f /etc/openldap/schema/core.schema ]; then 123 | SCHEMABASE=/etc/openldap/schema 124 | else 125 | SCHEMABASE=/etc/ldap/schema 126 | fi 127 | 128 | echo ${LDAPBASE} > .ldapbase 129 | 130 | mkdir ${LDAPBASE}/db 131 | cp ${LDAPCONF}/slapd.conf ${LDAPBASE}/ 132 | 133 | sed -i "s|/var/run/slapd/slapd.pid|${LDAPBASE}/slapd.pid|" ${LDAPBASE}/slapd.conf 134 | sed -i "s|/var/run/slapd/slapd.args|${LDAPBASE}/slapd.pid|" ${LDAPBASE}/slapd.conf 135 | sed -i "s|/var/lib/ldap|${LDAPBASE}/db|" ${LDAPBASE}/slapd.conf 136 | sed -i "s|/etc/ldap/schema|${SCHEMABASE}|" ${LDAPBASE}/slapd.conf 137 | 138 | nohup slapd -d3 -f ${LDAPBASE}/slapd.conf -h 'ldap://localhost:3389/' &> ${LDAPBASE}/slapd.log & 139 | 140 | # Give LDAP a few seconds to start 141 | sleep 3 142 | 143 | if [ ! -z "$VERBOSE" ]; then 144 | cat ${LDAPBASE}/slapd.log 145 | fi 146 | 147 | ldapadd -x -D 'cn=admin,dc=redmine,dc=org' -w password -H 'ldap://localhost:3389/' -f ${LDAPCONF}/test-ldap.ldif > /dev/null 148 | trace "LDAP Started" 149 | } 150 | 151 | run_tests() 152 | { 153 | setenv 154 | 155 | pushd $REDMINE_DIR 1> /dev/null 156 | 157 | if [ "$REDMINE" == "master" ] && [ "$RUBY_VERSION" == "2.4.3" ]; then 158 | bundle exec rake redmine:plugins:ldap_sync:coveralls:test $TRACE 159 | else 160 | bundle exec rake redmine:plugins:ldap_sync:test $TRACE 161 | fi 162 | 163 | popd 1> /dev/null 164 | } 165 | 166 | test_uninstall() 167 | { 168 | setenv 169 | 170 | pushd $REDMINE_DIR 1> /dev/null 171 | 172 | bundle exec rake $TRACE redmine:plugins NAME=redmine_ldap_sync VERSION=0 173 | 174 | popd 1> /dev/null 175 | } 176 | 177 | case "$1" in 178 | "clone_redmine") shift; clone_redmine $@;; 179 | "install_plugin_gemfile") shift; install_plugin_gemfile $@;; 180 | "prepare_redmine") shift; prepare_redmine $@;; 181 | "prepare_plugin") shift; prepare_plugin $@;; 182 | "start_ldap") shift; start_ldap $@;; 183 | "run_tests") shift; run_tests $@;; 184 | "test_uninstall") shift; test_uninstall $@;; 185 | *) echo "clone_redmine; install_plugin_gemfile; prepare_redmine; prepare_plugin; start_ldap; run_tests; test_uninstall";; 186 | esac 187 | -------------------------------------------------------------------------------- /test/fixtures/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tainewoo/redmine_ldap_sync/95219d5f0ab007db9975a6d0f8e32e78c1f36728/test/fixtures/.gitkeep -------------------------------------------------------------------------------- /test/fixtures/auth_sources.yml: -------------------------------------------------------------------------------- 1 | --- 2 | auth_sources_001: 3 | id: 1 4 | type: AuthSourceLdap 5 | name: 'LDAP test server' 6 | host: '127.0.0.1' 7 | port: 3389 8 | base_dn: 'DC=redmine,DC=org' 9 | account: 'cn=admin,dc=redmine,dc=org' 10 | account_password: password 11 | attr_login: uid 12 | attr_firstname: givenName 13 | attr_lastname: sn 14 | attr_mail: mail 15 | onthefly_register: true 16 | auth_sources_002: 17 | id: 2 18 | type: AuthSourceLdap 19 | name: 'LDAP test server 2' 20 | host: '127.0.0.2' 21 | port: 3389 22 | base_dn: 'OU=Person,DC=localhost,DC=net' 23 | attr_login: uid 24 | attr_firstname: givenName 25 | attr_lastname: sn 26 | attr_mail: mail 27 | onthefly_register: false 28 | -------------------------------------------------------------------------------- /test/fixtures/custom_fields.yml: -------------------------------------------------------------------------------- 1 | --- 2 | preferred_language: 3 | name: Preferred Language 4 | min_length: 0 5 | regexp: "" 6 | is_for_all: false 7 | type: UserCustomField 8 | max_length: 0 9 | possible_values: "" 10 | id: 1 11 | is_required: false 12 | field_format: string 13 | default_value: "en" 14 | editable: true 15 | position: 1 16 | uid_number: 17 | name: Uid Number 18 | min_length: 0 19 | regexp: "" 20 | is_for_all: false 21 | type: UserCustomField 22 | max_length: 0 23 | possible_values: "" 24 | id: 2 25 | is_required: true 26 | field_format: int 27 | default_value: 0 28 | editable: false 29 | position: 2 30 | custom_fields_003: 31 | name: Description 32 | min_length: 0 33 | regexp: "" 34 | is_for_all: false 35 | type: GroupCustomField 36 | max_length: 0 37 | possible_values: "" 38 | id: 3 39 | is_required: false 40 | field_format: string 41 | default_value: 'no description' 42 | editable: true 43 | position: 2 -------------------------------------------------------------------------------- /test/fixtures/email_addresses.yml: -------------------------------------------------------------------------------- 1 | --- 2 | email_address_001: 3 | id: 1 4 | user_id: 1 5 | address: admin@somenet.foo 6 | is_default: true 7 | created_on: 2006-07-19 19:34:07 +02:00 8 | updated_on: 2006-07-19 19:34:07 +02:00 9 | email_address_002: 10 | id: 2 11 | user_id: 2 12 | address: rhill@somenet.foo 13 | is_default: true 14 | created_on: 2006-07-19 19:34:07 +02:00 15 | updated_on: 2006-07-19 19:34:07 +02:00 16 | email_address_003: 17 | id: 3 18 | user_id: 3 19 | address: jsmith@somenet.foo 20 | is_default: true 21 | created_on: 2006-07-19 19:34:07 +02:00 22 | updated_on: 2006-07-19 19:34:07 +02:00 23 | email_address_004: 24 | id: 4 25 | user_id: 4 26 | address: dlopper@somenet.foo 27 | is_default: true 28 | created_on: 2006-07-19 19:34:07 +02:00 29 | updated_on: 2006-07-19 19:34:07 +02:00 30 | email_address_005: 31 | id: 5 32 | user_id: 5 33 | address: dlopper2@somenet.foo 34 | is_default: true 35 | created_on: 2006-07-19 19:34:07 +02:00 36 | updated_on: 2006-07-19 19:34:07 +02:00 37 | email_address_007: 38 | id: 7 39 | user_id: 7 40 | address: someone@foo.bar 41 | is_default: true 42 | created_on: 2006-07-19 19:34:07 +02:00 43 | updated_on: 2006-07-19 19:34:07 +02:00 44 | email_address_008: 45 | id: 8 46 | user_id: 8 47 | address: miscuser8@foo.bar 48 | is_default: true 49 | created_on: 2006-07-19 19:34:07 +02:00 50 | updated_on: 2006-07-19 19:34:07 +02:00 51 | email_address_009: 52 | id: 9 53 | user_id: 9 54 | address: miscuser9@foo.bar 55 | is_default: true 56 | created_on: 2006-07-19 19:34:07 +02:00 57 | updated_on: 2006-07-19 19:34:07 +02:00 58 | email_address_010: 59 | id: 10 60 | user_id: 12 61 | address: rubycalm@fakemail.com 62 | is_default: true 63 | created_on: 2006-07-19 19:34:07 +02:00 64 | updated_on: 2006-07-19 19:34:07 +02:00 -------------------------------------------------------------------------------- /test/fixtures/groups_users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | rynever_loadgeek: 3 | group_id: 11 4 | user_id: 8 5 | rynever_someone: 6 | group_id: 11 7 | user_id: 7 8 | rynever_rubycalm: 9 | group_id: 11 10 | user_id: 12 11 | therb_someone: 12 | group_id: 10 13 | user_id: 7 14 | issue_149_someone: 15 | group_id: 13 16 | user_id: 12 -------------------------------------------------------------------------------- /test/fixtures/ldap/names.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # encoding: utf-8 3 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 4 | # 5 | # This file is part of Redmine LDAP Sync. 6 | # 7 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with Redmine LDAP Sync. If not, see . 19 | rng = Random.new(12345) 20 | USERS = 5 21 | GROUPS = 10 22 | 23 | puts "dn: dc=redmine,dc=org 24 | objectClass: top 25 | objectClass: dcObject 26 | objectClass: organization 27 | o: redmine.org 28 | dc: redmine 29 | 30 | dn: cn=admin,dc=redmine,dc=org 31 | objectClass: simpleSecurityObject 32 | objectClass: organizationalRole 33 | cn: admin 34 | description: LDAP administrator 35 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 36 | 37 | dn: ou=Person,dc=redmine,dc=org 38 | ou: Person 39 | objectClass: organizationalUnit 40 | 41 | dn: ou=Group,dc=redmine,dc=org 42 | ou: Group 43 | objectClass: organizationalUnit\n\n" 44 | 45 | user = 46 | 'dn: uid=%{username},ou=Person,dc=redmine,dc=org 47 | mail: %{mail} 48 | uid: %{username} 49 | cn: %{cn} 50 | preferredLanguage: %{language} 51 | uidNumber: %{uidNumber} 52 | gidNumber: 100 53 | homeDirectory: /home/%{homeDir} 54 | objectClass: posixAccount 55 | objectClass: person 56 | objectClass: inetOrgPerson 57 | givenName: %{givenName} 58 | sn: %{sn} 59 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 60 | loginShell: /bin/sh 61 | ' 62 | 63 | group_member = "member: cn=%{groupname},ou=Group,dc=redmine,dc=org\n" 64 | user_member = "member: uid=%{username},ou=Person,dc=redmine,dc=org\n" 65 | user_group = "o: %{gidNumber}\n" 66 | group_group = "o: %{gidNumber}\n" 67 | 68 | group = 69 | 'dn: cn=%{groupname},ou=Group,dc=redmine,dc=org 70 | objectClass: groupOfNames 71 | objectClass: posixAccount 72 | homeDirectory: /nonexistent 73 | gidNumber: %{gidNumber} 74 | uidNumber: %{gidNumber} 75 | uid: %{groupname} 76 | cn: %{groupname} 77 | %{members}' 78 | 79 | groups = %w( 80 | Säyeldas Iardum Bluil Anbely Issekin Briklør Enden 81 | Rynever Worathest Therß Meyl Oany Whod Tiaris 82 | Belecer Rill Strycheser Ustuq Issk Hatosentan Llant 83 | Ghaoll Kimshy Irenth Swien Endash Denardon Hatcer 84 | Aughny Kibyno Tonage Serende Bietroth Engech Aseta 85 | Tanusk Umf Danasho Rakm Honeld Maedtas Skelmos 86 | Sulgard Tonid Leris Rothit Awkin Sand Delusk 87 | Warad Dihen Otiao Therkal Wage Emum Veaw 88 | Inequa Lyeack Agecerat Achkim Enrak Gulut Oveso 89 | Toniv Kalq Tiaorm Calltia Ascerem Kaltia Seraufst 90 | Honibi Quadeny Ridasi Tegh Teguno Sewarhat Poltiaeld 91 | Polhini Liwaren Atler Tinenhin Quever Tanhtor Nysos 92 | Brint Ageaughtor Lleef Yiew Arbche Perusul Ghash 93 | Etum Itxash Lamur Richit Smuaddan Fyzin Endeves 94 | Iuski Tinrothu Lododu Iuste Dimyn Podynen Lopisy 95 | Untros Igara Emique Ruperash Awend Slyaugh Ackrandel 96 | Ustech Anarr Ightwor Aleing Nyrak Cheash Itora 97 | ) 98 | 99 | users = %w( LoadGeek 100 | tweetmicro 101 | systemhack 102 | tweetsave 103 | microunit 104 | browserclient 105 | webfiber 106 | cabledrive 107 | graphicsfiber 108 | drivechip 109 | iconfiber 110 | corescript 111 | opticipod 112 | blogarray 113 | processipod 114 | waremicro 115 | digiprocess 116 | digiware 117 | iconoptic 118 | scripttweet 119 | clickturtle 120 | ringshark 121 | popsnake 122 | clickowl 123 | tockgiraffe 124 | itchgiraffe 125 | itchdonkey 126 | clickworm 127 | blowgorilla 128 | scratcheagle 129 | yellowcruel 130 | rubycalm 131 | golldhorror 132 | rubyhopeless 133 | blackhappy 134 | whitecross 135 | limegrumpy 136 | lilacgrim 137 | mauvecrrazy 138 | rosemap 139 | leetbroccoli 140 | banana 141 | carrot 142 | winnuts 143 | lolchips 144 | wthfrogs 145 | lmaococonut 146 | winpie 147 | lmaobanana 148 | failcoconut ) 149 | 150 | names = ['Christián Earheart', 151 | 'Rae Croll', 152 | 'Darryl Ditto', 153 | 'Nelson Meriwether', 154 | 'Elnora Gershon', 155 | 'Odessa Stingley', 156 | 'Kelly Cafferty', 157 | 'Dona Austria', 158 | 'Ericka Strohl', 159 | 'Lakisha Kouba', 160 | 'Fernando Dymond', 161 | 'Amie Rodreguez', 162 | 'Tyrone Winders', 163 | 'Rae Degner', 164 | 'Darren Canez', 165 | 'Earnestine Zahm', 166 | 'Fernando Stemm', 167 | 'Tanisha Sprowl', 168 | 'Saundra Nokes', 169 | 'Darren Czerwinski', 170 | 'Lenore Messersmith', 171 | 'Ashlee Stolz', 172 | 'Darryl Schaner', 173 | 'Sofia Lacayo', 174 | 'Sofia Wiers', 175 | 'Lonnie Mccarville', 176 | 'Allie Bavaro', 177 | 'Sharron Conine', 178 | 'Guy Ledger', 179 | 'Carmella Kleffman', 180 | 'Clayton Rodrick', 181 | 'Kathrine Solley', 182 | 'Annabelle Riser', 183 | 'Julio Wurster', 184 | 'Earnestine Camille', 185 | 'Hugh Juarbe', 186 | 'Guy Hodgin', 187 | 'Jamie Alpers', 188 | 'Benita Mccrimmon', 189 | 'Earnestine Guidroz', 190 | 'Ted Formica', 191 | 'Jamie Auton', 192 | 'Guy Gagnier', 193 | 'Tanisha Dahlen', 194 | 'Annabelle Spillane', 195 | 'Noemi Mcalexander', 196 | 'Allan Hynd', 197 | 'Fernando Schaner', 198 | 'Erik Haubert', 199 | 'Jeanie Mazzarella' 200 | ] 201 | 202 | languages = %w( ar ca de en eu fr hr it lt mn pl ro sl sr-YU tr zh-TWbg cs el es fa gl hu ja lv nl pt-BR ru sq sv uk zhbs da en-GB et fi he id ko mk no pt sk sr th vi ) 203 | 204 | users = users[0...USERS] 205 | names = names[0...USERS] 206 | groups = groups[0...GROUPS] 207 | 208 | s_users = Hash.new{|h,k| h[k] = ''} 209 | s_groups = Hash.new{|h,k| h[k] = ''} 210 | 211 | n = 300 212 | users.zip(names).each do |username, fullname| 213 | s_users[username] = user. 214 | gsub('%{username}', username). 215 | gsub('%{cn}', fullname). 216 | gsub('%{givenName}', fullname.split(' ')[0]). 217 | gsub('%{sn}', fullname.split(' ')[1]). 218 | gsub('%{mail}', "#{username.downcase}@fakemail.com"). 219 | gsub('%{uidNumber}', (n += 1).to_s ). 220 | gsub('%{homeDir}', username). 221 | gsub('%{language}', languages.sample(:random => rng)) 222 | end 223 | n = 4000 224 | groups.each do |groupname| 225 | gidNumber = (n += 1).to_s 226 | members = "" 227 | selected_users = [] 228 | selected_groups = [] 229 | (1..(1+rng.rand(3))).each do |i| 230 | if rng.rand(2) == 0 231 | name = (users - selected_users).sample(:random => rng) 232 | members += user_member.gsub('%{username}', name) 233 | selected_users << name 234 | s_users[name] += user_group.gsub('%{gidNumber}', gidNumber) 235 | else 236 | name = (groups - selected_groups).sample(:random => rng) 237 | members += group_member.gsub('%{groupname}', name) 238 | selected_groups << name 239 | s_groups[name] += group_group.gsub('%{gidNumber}', gidNumber) 240 | end 241 | end 242 | s_groups[groupname] = group. 243 | gsub('%{groupname}', groupname). 244 | gsub('%{gidNumber}', gidNumber). 245 | gsub('%{members}', members) + s_groups[groupname] 246 | end 247 | 248 | # Write everything to stdout 249 | puts s_users.values.join("\n") 250 | puts 251 | puts s_groups.values.join("\n") 252 | 253 | puts ' 254 | dn: cn=MicroUsers,ou=Group,dc=redmine,dc=org 255 | objectclass: groupOfURLs 256 | cn: MicroUsers 257 | memberURL: ldap:///ou=Person,dc=redmine,dc=org??sub?(uid=*micro*) 258 | 259 | dn: cn=TweetUsers,ou=Group,dc=redmine,dc=org 260 | objectclass: groupOfURLs 261 | cn: TweetUsers 262 | memberURL: ldap:///ou=Person,dc=redmine,dc=org??sub?(uid=*tweet*)' 263 | -------------------------------------------------------------------------------- /test/fixtures/ldap/slapd.conf: -------------------------------------------------------------------------------- 1 | # 2 | # LDAP Defaults 3 | # 4 | 5 | # See ldap.conf(5) for details 6 | # This file should be world readable but not world writable. 7 | 8 | #BASE dc=example,dc=com 9 | #URI ldap://ldap.example.com ldap://ldap-master.example.com:666 10 | 11 | #SIZELIMIT 12 12 | #TIMELIMIT 15 13 | #DEREF never 14 | 15 | # TLS certificates (needed for GnuTLS) 16 | #TLS_CACERT /etc/ssl/certs/ca-certificates.crt 17 | 18 | # Sample OpenLDAP configuration file for Redmine LDAP test server 19 | # 20 | #ucdata-path /var/lib/ldap/ucdata 21 | moduleload back_hdb.la 22 | moduleload memberof.la 23 | moduleload dynlist.la 24 | 25 | include /etc/ldap/schema/core.schema 26 | include /etc/ldap/schema/cosine.schema 27 | include /etc/ldap/schema/inetorgperson.schema 28 | include /etc/ldap/schema/openldap.schema 29 | include /etc/ldap/schema/nis.schema 30 | include /etc/ldap/schema/dyngroup.schema 31 | include /etc/ldap/schema/ppolicy.schema 32 | 33 | pidfile /var/run/slapd/slapd.pid 34 | argsfile /var/run/slapd/slapd.args 35 | 36 | database hdb 37 | suffix "dc=redmine,dc=org" 38 | rootdn "cn=admin,dc=redmine,dc=org" 39 | rootpw password 40 | directory /var/lib/ldap 41 | # Indices to maintain 42 | index objectClass eq 43 | 44 | overlay memberof 45 | memberof-group-oc groupOfNames 46 | memberof-member-ad member 47 | memberof-memberof-ad memberOf 48 | 49 | overlay dynlist 50 | dynlist-attrset groupOfURLs memberURL member -------------------------------------------------------------------------------- /test/fixtures/ldap/test-ldap.ldif: -------------------------------------------------------------------------------- 1 | dn: dc=redmine,dc=org 2 | objectClass: top 3 | objectClass: dcObject 4 | objectClass: organization 5 | o: redmine.org 6 | dc: redmine 7 | 8 | dn: cn=admin,dc=redmine,dc=org 9 | objectClass: simpleSecurityObject 10 | objectClass: organizationalRole 11 | cn: admin 12 | description: LDAP administrator 13 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 14 | 15 | dn: ou=Person,dc=redmine,dc=org 16 | ou: Person 17 | objectClass: organizationalUnit 18 | 19 | dn: ou=Group,dc=redmine,dc=org 20 | ou: Group 21 | objectClass: organizationalUnit 22 | 23 | dn: uid=example1,ou=Person,dc=redmine,dc=org 24 | objectClass: posixAccount 25 | objectClass: inetOrgPerson 26 | gidNumber: 0 27 | givenName: Example 28 | sn: One 29 | uid: example1 30 | homeDirectory: /home/example1 31 | cn: Example One 32 | uidNumber: 900 33 | mail: example1@redmine.org 34 | userPassword:: e1NIQX1mRXFOQ2NvM1lxOWg1WlVnbEQzQ1pKVDRsQnM9 35 | 36 | dn: uid=edavis,ou=Person,dc=redmine,dc=org 37 | objectClass: posixAccount 38 | objectClass: top 39 | objectClass: inetOrgPerson 40 | gidNumber: 0 41 | givenName: Eric 42 | sn: Davis 43 | uid: edavis 44 | mail: edavis@littlestreamsoftware.com 45 | homeDirectory: /home/edavis 46 | cn: Eric Davis 47 | uidNumber: 902 48 | userPassword:: e1NIQX1mRXFOQ2NvM1lxOWg1WlVnbEQzQ1pKVDRsQnM9 49 | o: 4003 50 | o: 100 51 | 52 | dn: uid=LoadGeek,ou=Person,dc=redmine,dc=org 53 | mail: loadgeek@fakemail.com 54 | uid: LoadGeek 55 | cn: Christián Earheart 56 | preferredLanguage: pt 57 | uidNumber: 301 58 | gidNumber: 100 59 | homeDirectory: /home/loadgeek 60 | objectClass: posixAccount 61 | objectClass: person 62 | objectClass: inetOrgPerson 63 | objectClass: pwdPolicy 64 | givenName: Christián 65 | sn: Earheart 66 | description: Earheart User 67 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 68 | loginShell: /bin/sh 69 | pwdAttribute: 2.5.4.35 70 | pwdLockout: TRUE 71 | o: 4005 72 | o: 4007 73 | o: 4009 74 | o: 4015 75 | 76 | dn: uid=tweetmicro,ou=Person,dc=redmine,dc=org 77 | mail: tweetmicro@fakemail.com 78 | uid: tweetmicro 79 | cn: Rae Croll 80 | preferredLanguage: ar 81 | uidNumber: 302 82 | gidNumber: 100 83 | homeDirectory: /home/tweetmicro 84 | description: Tweetmicro user [disabled] 85 | objectClass: posixAccount 86 | objectClass: person 87 | objectClass: inetOrgPerson 88 | givenName: Rae 89 | sn: Croll 90 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 91 | loginShell: /bin/sh 92 | o: 4001 93 | o: 4006 94 | o: 4008 95 | o: 4007 96 | 97 | dn: uid=systemhack,ou=Person,dc=redmine,dc=org 98 | mail: systemhack@fakemail.com 99 | uid: systemhack 100 | cn: Darryl Ditto 101 | preferredLanguage: da 102 | uidNumber: 303 103 | gidNumber: 100 104 | homeDirectory: /home/systemhack 105 | objectClass: posixAccount 106 | objectClass: person 107 | objectClass: inetOrgPerson 108 | givenName: Darryl 109 | sn: Ditto 110 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 111 | loginShell: /bin/sh 112 | o: 4002 113 | o: 4003 114 | o: 4006 115 | 116 | dn: uid=tweetsave,ou=Person,dc=redmine,dc=org 117 | mail: tweetsave@fakemail.com 118 | uid: tweetsave 119 | cn: Nelson Meriwether 120 | preferredLanguage: pl 121 | uidNumber: 304 122 | gidNumber: 100 123 | homeDirectory: /home/tweetsave 124 | objectClass: posixAccount 125 | objectClass: person 126 | objectClass: inetOrgPerson 127 | givenName: Nelson 128 | sn: Meriwether 129 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 130 | loginShell: /bin/sh 131 | o: 4002 132 | o: 4006 133 | 134 | dn: uid=microunit,ou=Person,dc=redmine,dc=org 135 | mail: microunit@fakemail.com 136 | uid: microunit 137 | cn: Elnora Gershon 138 | preferredLanguage: vi 139 | uidNumber: 305 140 | gidNumber: 100 141 | homeDirectory: /home/microunit 142 | objectClass: posixAccount 143 | objectClass: person 144 | objectClass: inetOrgPerson 145 | givenName: Elnora 146 | sn: Gershon 147 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 148 | loginShell: /bin/sh 149 | o: 4002 150 | o: 4005 151 | o: 4007 152 | o: 4008 153 | o: 4009 154 | o: 4015 155 | 156 | dn: uid=incomplete,ou=Person,dc=redmine,dc=org 157 | uid: incomplete 158 | cn: Incomplete User 159 | preferredLanguage: pt 160 | description: User without all the required fields 161 | uidNumber: 306 162 | gidNumber: 100 163 | homeDirectory: /home/incomplete 164 | objectClass: posixAccount 165 | objectClass: person 166 | objectClass: inetOrgPerson 167 | sn: User 168 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 169 | loginShell: /bin/sh 170 | o: 4002 171 | o: 4003 172 | o: 4006 173 | o: 4009 174 | 175 | dn: uid=rubycalm,ou=Person,dc=redmine,dc=org 176 | mail: rubycalm@fakemail.com 177 | uid: rubycalm 178 | cn: Fernando Stemm 179 | preferredLanguage: va 180 | description: User with primary group Smuaddan 181 | uidNumber: 307 182 | gidNumber: 4000 183 | homeDirectory: /home/incomplete 184 | objectClass: posixAccount 185 | objectClass: person 186 | objectClass: inetOrgPerson 187 | givenName: Fernando 188 | sn: Stemm 189 | userPassword: {SSHA}Si9/UcgqKWBlN/+SQb+X1IHZnokzaicm 190 | loginShell: /bin/sh 191 | o: 4001 192 | o: 4016 193 | 194 | dn: cn=Smuaddan,ou=Group,dc=redmine,dc=org 195 | objectClass: groupOfNames 196 | objectClass: posixAccount 197 | homeDirectory: /nonexistent 198 | gidNumber: 100 199 | uidNumber: 100 200 | uid: Smuaddan 201 | cn: Smuaddan 202 | member: uid=edavis,ou=Person,dc=redmine,dc=org 203 | 204 | dn: cn=Rill,ou=Group,dc=redmine,dc=org 205 | objectClass: groupOfNames 206 | objectClass: posixAccount 207 | homeDirectory: /nonexistent 208 | gidNumber: 4000 209 | uidNumber: 4000 210 | uid: Rill 211 | cn: Rill 212 | member: uid=tweetmicro,ou=Person,dc=redmine,dc=org 213 | 214 | dn: cn=Rynever,ou=Group,dc=redmine,dc=org 215 | objectClass: groupOfNames 216 | objectClass: posixAccount 217 | homeDirectory: /nonexistent 218 | gidNumber: 4001 219 | uidNumber: 4001 220 | uid: Rynever 221 | cn: Rynever 222 | member: uid=tweetmicro,ou=Person,dc=redmine,dc=org 223 | member: uid=rubycalm,ou=Person,dc=redmine,dc=org 224 | 225 | dn: cn=Worathest,ou=Group,dc=redmine,dc=org 226 | objectClass: groupOfNames 227 | objectClass: posixAccount 228 | homeDirectory: /nonexistent 229 | gidNumber: 4002 230 | uidNumber: 4002 231 | uid: Worathest 232 | cn: Worathest 233 | member: uid=microunit,ou=Person,dc=redmine,dc=org 234 | member: uid=tweetsave,ou=Person,dc=redmine,dc=org 235 | member: uid=systemhack,ou=Person,dc=redmine,dc=org 236 | member: uid=incomplete,ou=Person,dc=redmine,dc=org 237 | o: 4004 238 | 239 | dn: cn=Säyeldas,ou=Group,dc=redmine,dc=org 240 | objectClass: groupOfNames 241 | objectClass: posixAccount 242 | homeDirectory: /nonexistent 243 | gidNumber: 4003 244 | uidNumber: 4003 245 | uid: Säyeldas 246 | cn: Säyeldas 247 | member: uid=systemhack,ou=Person,dc=redmine,dc=org 248 | member: uid=incomplete,ou=Person,dc=redmine,dc=org 249 | member: uid=edavis,ou=Person,dc=redmine,dc=org 250 | o: 4004 251 | o: 4008 252 | 253 | dn: cn=Briklør,ou=Group,dc=redmine,dc=org 254 | objectClass: groupOfNames 255 | objectClass: posixAccount 256 | homeDirectory: /nonexistent 257 | gidNumber: 4004 258 | uidNumber: 4004 259 | uid: Briklør 260 | cn: Briklør 261 | member: cn=Worathest,ou=Group,dc=redmine,dc=org 262 | member: cn=Säyeldas,ou=Group,dc=redmine,dc=org 263 | o: 4005 264 | 265 | dn: cn=Bluil,ou=Group,dc=redmine,dc=org 266 | objectClass: groupOfNames 267 | objectClass: posixAccount 268 | homeDirectory: /nonexistent 269 | gidNumber: 4005 270 | uidNumber: 4005 271 | uid: Bluil 272 | cn: Bluil 273 | member: cn=Briklør,ou=Group,dc=redmine,dc=org 274 | member: uid=microunit,ou=Person,dc=redmine,dc=org 275 | member: uid=LoadGeek,ou=Person,dc=redmine,dc=org 276 | 277 | dn: cn=Anbely,ou=Group,dc=redmine,dc=org 278 | objectClass: groupOfNames 279 | objectClass: posixAccount 280 | homeDirectory: /nonexistent 281 | gidNumber: 4006 282 | uidNumber: 4006 283 | uid: Anbely 284 | cn: Anbely 285 | member: uid=tweetsave,ou=Person,dc=redmine,dc=org 286 | member: uid=systemhack,ou=Person,dc=redmine,dc=org 287 | member: uid=incomplete,ou=Person,dc=redmine,dc=org 288 | member: uid=tweetmicro,ou=Person,dc=redmine,dc=org 289 | 290 | dn: cn=Issekin,ou=Group,dc=redmine,dc=org 291 | objectClass: groupOfNames 292 | objectClass: posixAccount 293 | homeDirectory: /nonexistent 294 | gidNumber: 4007 295 | uidNumber: 4007 296 | uid: Issekin 297 | cn: Issekin 298 | member: uid=microunit,ou=Person,dc=redmine,dc=org 299 | member: uid=tweetmicro,ou=Person,dc=redmine,dc=org 300 | member: uid=LoadGeek,ou=Person,dc=redmine,dc=org 301 | 302 | 303 | dn: cn=Enden,ou=Group,dc=redmine,dc=org 304 | objectClass: groupOfNames 305 | objectClass: posixAccount 306 | homeDirectory: /nonexistent 307 | gidNumber: 4008 308 | uidNumber: 4008 309 | uid: Enden 310 | cn: Enden 311 | member: cn=Säyeldas,ou=Group,dc=redmine,dc=org 312 | member: uid=microunit,ou=Person,dc=redmine,dc=org 313 | member: uid=tweetmicro,ou=Person,dc=redmine,dc=org 314 | 315 | 316 | dn: cn=Therß,ou=Group,dc=redmine,dc=org 317 | objectClass: groupOfNames 318 | objectClass: posixAccount 319 | homeDirectory: /nonexistent 320 | gidNumber: 4009 321 | uidNumber: 4009 322 | uid: Therß 323 | cn: Therß 324 | description: Therß Team Group 325 | member: cn=Iardum,ou=Group,dc=redmine,dc=org 326 | member: cn=LoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamLoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamdipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquam,ou=Group,dc=redmine,dc=org 327 | member: uid=LoadGeek,ou=Person,dc=redmine,dc=org 328 | member: uid=microunit,ou=Person,dc=redmine,dc=org 329 | member: uid=incomplete,ou=Person,dc=redmine,dc=org 330 | o: 4010 331 | o: 4011 332 | 333 | dn: cn=Iardum,ou=Group,dc=redmine,dc=org 334 | objectClass: groupOfNames 335 | objectClass: posixAccount 336 | homeDirectory: /nonexistent 337 | gidNumber: 4010 338 | uidNumber: 4010 339 | uid: Iardum 340 | cn: Iardum 341 | member: cn=Therß,ou=Group,dc=redmine,dc=org 342 | o: 4009 343 | 344 | dn: cn=LoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamLoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamdipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquam,ou=Group,dc=redmine,dc=org 345 | objectClass: groupOfNames 346 | objectClass: posixAccount 347 | homeDirectory: /nonexistent 348 | gidNumber: 4011 349 | uidNumber: 4011 350 | uid: LoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamLoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamdipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquam 351 | cn: LoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamLoremipsumdolorsitametconsectetueradipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquamdipiscingelitseddiamnonummynibheuismodtinciduntutlaoreetdoloremagnaaliquam 352 | member: cn=Therß,ou=Group,dc=redmine,dc=org 353 | 354 | dn: cn=IT отдел Системные,ou=Group,dc=redmine,dc=org 355 | objectClass: groupOfNames 356 | objectClass: posixAccount 357 | homeDirectory: /nonexistent 358 | gidNumber: 4015 359 | uidNumber: 4015 360 | uid: IT отдел Системные 361 | cn: IT отдел Системные 362 | description: Issue #93 363 | member: uid=LoadGeek,ou=Person,dc=redmine,dc=org 364 | member: uid=microunit,ou=Person,dc=redmine,dc=org 365 | 366 | dn: cn=Příliš žluťoučký kůň úpěl ďábelské ódy,ou=Group,dc=redmine,dc=org 367 | objectClass: groupOfNames 368 | objectClass: posixAccount 369 | homeDirectory: /nonexistent 370 | gidNumber: 4016 371 | uidNumber: 4016 372 | uid: Příliš žluťoučký kůň úpěl ďábelské ódy 373 | cn: Příliš žluťoučký kůň úpěl ďábelské ódy 374 | description: Issue #149 375 | member: uid=rubycalm,ou=Person,dc=redmine,dc=org 376 | 377 | dn: cn=MicroUsers,ou=Group,dc=redmine,dc=org 378 | objectclass: groupOfURLs 379 | cn: MicroUsers 380 | memberURL: ldap:///ou=Person,dc=redmine,dc=org??sub?(uid=*micro*) 381 | 382 | dn: cn=TweetUsers,ou=Group,dc=redmine,dc=org 383 | objectclass: groupOfURLs 384 | cn: TweetUsers 385 | memberURL: ldap:///ou=Person,dc=redmine,dc=org??sub?(uid=*tweet*) -------------------------------------------------------------------------------- /test/fixtures/member_roles.yml: -------------------------------------------------------------------------------- 1 | --- 2 | member_roles_001: 3 | id: 300 4 | role_id: 1 5 | member_id: 300 6 | member_roles_002: 7 | id: 302 8 | role_id: 1 9 | member_id: 301 10 | inherited_from: 300 11 | member_roles_003: 12 | id: 303 13 | role_id: 2 14 | member_id: 302 15 | -------------------------------------------------------------------------------- /test/fixtures/members.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ldap_sync_members: 3 | created_on: 2010-07-19 19:35:33 +02:00 4 | project_id: 201 5 | id: 300 6 | user_id: 10 7 | mail_notification: false 8 | ldap_sync_members_1: 9 | id: 301 10 | created_on: 2010-07-19 19:35:33 +02:00 11 | project_id: 201 12 | user_id: 7 13 | mail_notification: true 14 | ldap_sync_members_2: 15 | id: 302 16 | created_on: 2010-07-19 19:35:33 +02:00 17 | project_id: 202 18 | user_id: 7 19 | mail_notification: true -------------------------------------------------------------------------------- /test/fixtures/projects.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ldap_sync_project: 3 | created_on: 2011-07-19 19:13:59 +02:00 4 | name: LDAP Sync 5 | updated_on: 2013-06-09 10:13:05 +02:00 6 | id: 201 7 | description: LDAP Sync redmine plugin 8 | homepage: https://github.com/thorin/redmine_ldap_sync 9 | is_public: true 10 | identifier: ldap_sync 11 | redmine_project: 12 | created_on: 2011-07-19 19:13:59 +02:01 13 | name: Redmine 14 | updated_on: 2013-06-09 10:13:05 +02:01 15 | id: 202 16 | description: Redmine Issue Tracker 17 | homepage: https://github.com/redmine/redmine 18 | is_public: true 19 | identifier: redmine 20 | -------------------------------------------------------------------------------- /test/fixtures/roles.yml: -------------------------------------------------------------------------------- 1 | --- 2 | manager: 3 | name: Manager 4 | id: 1 5 | builtin: 0 6 | issues_visibility: all 7 | permissions: | 8 | --- 9 | - :add_project 10 | - :edit_project 11 | - :close_project 12 | - :select_project_modules 13 | - :manage_members 14 | - :manage_versions 15 | - :manage_categories 16 | - :view_issues 17 | - :add_issues 18 | - :edit_issues 19 | - :manage_issue_relations 20 | - :manage_subtasks 21 | - :add_issue_notes 22 | - :move_issues 23 | - :delete_issues 24 | - :view_issue_watchers 25 | - :add_issue_watchers 26 | - :set_issues_private 27 | - :set_notes_private 28 | - :view_private_notes 29 | - :delete_issue_watchers 30 | - :manage_public_queries 31 | - :save_queries 32 | - :view_gantt 33 | - :view_calendar 34 | - :log_time 35 | - :view_time_entries 36 | - :edit_time_entries 37 | - :delete_time_entries 38 | - :manage_news 39 | - :comment_news 40 | - :view_documents 41 | - :add_documents 42 | - :edit_documents 43 | - :delete_documents 44 | - :view_wiki_pages 45 | - :export_wiki_pages 46 | - :view_wiki_edits 47 | - :edit_wiki_pages 48 | - :delete_wiki_pages_attachments 49 | - :protect_wiki_pages 50 | - :delete_wiki_pages 51 | - :rename_wiki_pages 52 | - :add_messages 53 | - :edit_messages 54 | - :delete_messages 55 | - :manage_boards 56 | - :view_files 57 | - :manage_files 58 | - :browse_repository 59 | - :manage_repository 60 | - :view_changesets 61 | - :manage_related_issues 62 | - :manage_project_activities 63 | 64 | position: 1 -------------------------------------------------------------------------------- /test/fixtures/settings.yml: -------------------------------------------------------------------------------- 1 | redmine_ldap_setting: 2 | name: plugin_redmine_ldap_sync 3 | updated_on: <%= Time.now.to_s(:db) %> 4 | value: | 5 | --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess 6 | 1: !ruby/hash:ActiveSupport::HashWithIndifferentAccess 7 | active: true 8 | groups_base_dn: OU=Group,DC=redmine,DC=org 9 | class_user: person 10 | users_search_scope: subtree 11 | class_group: groupOfNames 12 | groupname_pattern: '' 13 | group_search_filter: '' 14 | account_locked_test: flags.include? '[disabled]' 15 | group_membership: on_groups 16 | nested_groups: on_parents 17 | groupname: cn 18 | account_flags: description 19 | member: member 20 | user_memberid: dn 21 | user_groups: o 22 | groupid: gidNumber 23 | parent_group: o 24 | group_parentid: gidNumber 25 | member_group: member 26 | group_memberid: dn 27 | required_group: '' 28 | fixed_group: ldap.users 29 | create_groups: '1' 30 | create_users: '1' 31 | sync_on_login: 'user_fields_and_groups' 32 | dyngroups: '' 33 | admin_group: Itora 34 | group_fields_to_sync: 35 | - '3' 36 | user_fields_to_sync: 37 | - firstname 38 | - lastname 39 | - mail 40 | - '1' 41 | - '2' 42 | user_ldap_attrs: !ruby/hash:ActiveSupport::HashWithIndifferentAccess 43 | '1': preferredLanguage 44 | '2': uidNumber 45 | group_ldap_attrs: !ruby/hash:ActiveSupport::HashWithIndifferentAccess 46 | '3': description 47 | 2: !ruby/hash:ActiveSupport::HashWithIndifferentAccess 48 | active: true -------------------------------------------------------------------------------- /test/fixtures/users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | admin: 3 | id: 1 4 | created_on: 2006-07-19 19:12:21 +02:00 5 | status: 1 6 | last_login_on: 2006-07-19 22:57:52 +02:00 7 | language: en 8 | # password = admin 9 | salt: 82090c953c4a0000a7db253b0691a6b4 10 | hashed_password: b5b6ff9543bf1387374cdfa27a54c96d236a7150 11 | updated_on: 2006-07-19 22:57:52 +02:00 12 | admin: true 13 | <% if Redmine::VERSION::MAJOR < 3 %> 14 | mail: admin@somenet.foo 15 | <% end %> 16 | lastname: Admin 17 | firstname: redMine 18 | auth_source_id: 19 | mail_notification: all 20 | login: admin 21 | type: User 22 | rhill: 23 | id: 2 24 | created_on: 2006-07-19 19:34:07 +02:00 25 | status: 1 26 | last_login_on: 27 | language: en 28 | # password = foo 29 | salt: 3126f764c3c5ac61cbfc103f25f934cf 30 | hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b 31 | updated_on: 2006-07-19 19:34:07 +02:00 32 | admin: false 33 | <% if Redmine::VERSION::MAJOR < 3 %> 34 | mail: rhill@somenet.foo 35 | <% end %> 36 | lastname: Hill 37 | firstname: Robert 38 | auth_source_id: 39 | mail_notification: all 40 | login: rhill 41 | type: User 42 | users_002: 43 | id: 3 44 | created_on: 2006-07-19 19:32:09 +02:00 45 | status: 1 46 | last_login_on: 2006-07-19 22:42:15 +02:00 47 | language: en 48 | # password = jsmith 49 | salt: 67eb4732624d5a7753dcea7ce0bb7d7d 50 | hashed_password: bfbe06043353a677d0215b26a5800d128d5413bc 51 | updated_on: 2006-07-19 22:42:15 +02:00 52 | admin: false 53 | <% if Redmine::VERSION::MAJOR < 3 %> 54 | mail: jsmith@somenet.foo 55 | <% end %> 56 | lastname: Smith 57 | firstname: John 58 | auth_source_id: 59 | mail_notification: all 60 | login: jsmith 61 | type: User 62 | users_003: 63 | id: 4 64 | created_on: 2006-07-19 19:33:19 +02:00 65 | status: 1 66 | last_login_on: 67 | language: en 68 | # password = foo 69 | salt: 7599f9963ec07b5a3b55b354407120c0 70 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed 71 | updated_on: 2006-07-19 19:33:19 +02:00 72 | admin: false 73 | <% if Redmine::VERSION::MAJOR < 3 %> 74 | mail: dlopper@somenet.foo 75 | <% end %> 76 | lastname: Lopper 77 | firstname: Dave 78 | auth_source_id: 79 | mail_notification: all 80 | login: dlopper 81 | type: User 82 | users_005: 83 | id: 5 84 | created_on: 2006-07-19 19:33:19 +02:00 85 | # Locked 86 | status: 3 87 | last_login_on: 88 | language: en 89 | hashed_password: 1 90 | updated_on: 2006-07-19 19:33:19 +02:00 91 | admin: false 92 | <% if Redmine::VERSION::MAJOR < 3 %> 93 | mail: dlopper2@somenet.foo 94 | <% end %> 95 | lastname: Lopper2 96 | firstname: Dave2 97 | auth_source_id: 98 | mail_notification: all 99 | login: dlopper2 100 | type: User 101 | users_006: 102 | id: 6 103 | created_on: 2006-07-19 19:33:19 +02:00 104 | status: 0 105 | last_login_on: 106 | language: '' 107 | hashed_password: 1 108 | updated_on: 2006-07-19 19:33:19 +02:00 109 | admin: false 110 | <% if Redmine::VERSION::MAJOR < 3 %> 111 | mail: '' 112 | <% end %> 113 | lastname: Anonymous 114 | firstname: '' 115 | auth_source_id: 116 | mail_notification: only_my_events 117 | login: '' 118 | type: AnonymousUser 119 | someone: 120 | id: 7 121 | created_on: 2006-07-19 19:33:19 +02:00 122 | status: 1 123 | last_login_on: 124 | language: '' 125 | hashed_password: 1 126 | updated_on: 2006-07-19 19:33:19 +02:00 127 | admin: false 128 | <% if Redmine::VERSION::MAJOR < 3 %> 129 | mail: someone@foo.bar 130 | <% end %> 131 | lastname: One 132 | firstname: Some 133 | auth_source_id: 1 134 | mail_notification: only_my_events 135 | login: someone 136 | type: User 137 | loadgeek: 138 | id: 8 139 | created_on: 2006-07-19 19:33:19 +02:00 140 | status: 1 141 | last_login_on: 142 | language: 'it' 143 | # password = foo 144 | salt: 7599f9963ec07b5a3b55b354407120c0 145 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed 146 | updated_on: 2006-07-19 19:33:19 +02:00 147 | admin: false 148 | <% if Redmine::VERSION::MAJOR < 3 %> 149 | mail: miscuser8@foo.bar 150 | <% end %> 151 | lastname: Misc 152 | firstname: User 153 | auth_source_id: 1 154 | mail_notification: only_my_events 155 | login: loadgeek 156 | type: User 157 | users_009: 158 | id: 9 159 | created_on: 2006-07-19 19:33:19 +02:00 160 | status: 1 161 | last_login_on: 162 | language: 'it' 163 | hashed_password: 1 164 | updated_on: 2006-07-19 19:33:19 +02:00 165 | admin: false 166 | <% if Redmine::VERSION::MAJOR < 3 %> 167 | mail: miscuser9@foo.bar 168 | <% end %> 169 | lastname: Misc 170 | firstname: User 171 | auth_source_id: 172 | mail_notification: only_my_events 173 | login: miscuser9 174 | type: User 175 | users_010: 176 | id: 12 177 | created_on: 2006-07-19 19:33:19 +02:00 178 | status: 1 179 | last_login_on: 180 | language: 'it' 181 | hashed_password: 1 182 | updated_on: 2006-07-19 19:33:19 +02:00 183 | admin: false 184 | <% if Redmine::VERSION::MAJOR < 3 %> 185 | mail: rubycalm@fakemail.com 186 | <% end %> 187 | lastname: Stemm 188 | firstname: Fernando 189 | auth_source_id: 1 190 | mail_notification: only_my_events 191 | login: rubycalm 192 | type: User 193 | therß: 194 | id: 10 195 | lastname: therß 196 | type: Group 197 | rynever: 198 | id: 11 199 | lastname: rynever 200 | type: Group 201 | issue_149: 202 | id: 13 203 | lastname: Příliš žluťoučký kůň úpěl ďábelské ódy 204 | type: Group -------------------------------------------------------------------------------- /test/functional/ldap_settings_controller_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../../test_helper', __FILE__) 19 | 20 | class LdapSettingsControllerTest < ActionController::TestCase 21 | fixtures :auth_sources, :users, :settings, :custom_fields 22 | 23 | setup do 24 | Setting.clear_cache 25 | @auth_source = auth_sources(:auth_sources_001) 26 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@auth_source.id) 27 | @request.session[:user_id] = 1 28 | end 29 | 30 | def test_should_get_index 31 | get :index 32 | assert_response :success 33 | assert_not_nil assigns(:ldap_settings) 34 | 35 | assert_select "table tr", 3 36 | assert_select "a", :text => 'LDAP test server', :count => 1 37 | assert_select "td", :text => '127.0.0.1', :count => 1 38 | assert_select "td", :text => '127.0.0.1', :count => 1 39 | end 40 | 41 | def test_should_get_base_settings_js 42 | get :base_settings, :format => 'js' 43 | assert_response :success 44 | assert_template 'ldap_settings/base_settings' 45 | end 46 | 47 | def test_should_redirect_to_get_edit_on_get_show 48 | get :show, params: { id: 1 } 49 | assert_redirected_to edit_ldap_setting_path(1) 50 | end 51 | 52 | def test_should_get_edit 53 | get :edit, params: { id: @auth_source.id } 54 | assert_response :success 55 | end 56 | 57 | def test_should_get_404 58 | get :edit, params: { id: 999 } 59 | assert_response :not_found 60 | end 61 | 62 | def test_should_disable_ldap_setting 63 | # Given that 64 | assert @ldap_setting.active?, "LdapSetting must be enabled" 65 | assert_equal 'member', @ldap_setting.member_group 66 | 67 | # When we do 68 | get :disable, params: { id: @ldap_setting.id } 69 | assert_redirected_to ldap_settings_path 70 | assert_match /success/, flash[:notice] 71 | 72 | # We should have 73 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@ldap_setting.id) 74 | assert_equal 'member', ldap_setting.member_group, 'LdapSetting is not the same' 75 | assert !ldap_setting.active?, "LdapSetting must be disabled" 76 | end 77 | 78 | def test_should_disable_an_invalid_ldap_setting 79 | # Given that 80 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(2) 81 | assert ldap_setting.active? 82 | 83 | # When we do 84 | get :disable, params: { id: ldap_setting.id } 85 | assert_redirected_to ldap_settings_path 86 | assert_match /success/, flash[:notice] 87 | 88 | # We should have 89 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(2) 90 | assert_nil ldap_setting.member_group, 'LdapSetting is not the same' 91 | assert !ldap_setting.active?, "LdapSetting must be disabled" 92 | end 93 | 94 | def test_should_enable_ldap_setting 95 | # Given that 96 | @ldap_setting.active = false; @ldap_setting.save 97 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@ldap_setting.id) 98 | assert !ldap_setting.active?, "LdapSetting must be disabled" 99 | assert_equal 'member', ldap_setting.member_group 100 | 101 | # When we do 102 | get :enable, params: { id: ldap_setting.id } 103 | assert_redirected_to ldap_settings_path 104 | assert_match /success/, flash[:notice] 105 | 106 | # We should have 107 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(ldap_setting.id) 108 | assert_equal 'member', ldap_setting.member_group, 'LdapSetting is not the same' 109 | assert ldap_setting.active?, "LdapSetting must be enabled" 110 | end 111 | 112 | def test_should_not_enable_ldap_setting_with_errors 113 | # Given that 114 | @ldap_setting.active = false; @ldap_setting.save 115 | @ldap_setting.send(:attribute=, :dyngroups, 'invalid') 116 | @ldap_setting.send(:settings=, @ldap_setting.send(:attributes)) 117 | 118 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@ldap_setting.id) 119 | assert !@ldap_setting.active?, 'LdapSetting must be disabled' 120 | assert_equal 'member', @ldap_setting.member_group 121 | 122 | # When we do 123 | get :enable, params: { id: @ldap_setting.id } 124 | assert_redirected_to ldap_settings_path 125 | assert_match /invalid settings/, flash[:error] 126 | 127 | # We should have 128 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@ldap_setting.id) 129 | assert_equal 'member', ldap_setting.member_group, 'LdapSetting is not the same' 130 | assert !ldap_setting.active?, "LdapSetting must be disabled" 131 | end 132 | 133 | def test_should_fail_with_error 134 | put :update, params: { 135 | id: @ldap_setting.id, 136 | ldap_setting: { 137 | auth_source_ldap_id: @auth_source_id, 138 | active: true, 139 | groupname: 'cn', 140 | groups_base_dn: 'groups_base_dn', 141 | class_group: 'group', 142 | class_user: nil, # Missing required field 143 | group_membership: 'on_members', 144 | groupid: 'groupid', 145 | nested_groups: '', 146 | user_groups: 'memberof', 147 | sync_on_login: '', 148 | dyngroups: '' 149 | } 150 | } 151 | assert assigns(:ldap_setting).errors.added?(:class_user, :blank), 'An error must be reported for :class_user' 152 | assert_response :success 153 | end 154 | 155 | def test_should_update_ldap_setting 156 | put :update, params: { 157 | id: @ldap_setting.id, 158 | ldap_setting: { 159 | auth_source_ldap_id: @auth_source_id, 160 | active: true, 161 | account_disabled_test: '', 162 | account_flags: '', 163 | attributes_to_sync: '', 164 | class_group: 'group', 165 | class_user: 'user', 166 | create_groups: '', 167 | create_users: '', 168 | fixed_group: '', 169 | group_memberid: '', 170 | group_membership: 'on_members', 171 | group_parentid: '', 172 | group_search_filter: '', 173 | groupid: 'groupid', 174 | groupname: 'cn', 175 | groupname_pattern: '', 176 | groups_base_dn: 'groups_base_dn', 177 | member: '', 178 | member_group: '', 179 | nested_groups: '', 180 | parent_group: '', 181 | required_group: '', 182 | user_fields_to_sync: [], 183 | group_fields_to_sync: [], 184 | user_ldap_attrs: {}, 185 | group_ldap_attrs: {}, 186 | user_groups: 'memberof', 187 | user_memberid: '', 188 | sync_on_login: '', 189 | dyngroups: '' 190 | } 191 | } 192 | assert_redirected_to ldap_settings_path 193 | assert assigns(:ldap_setting).valid? 194 | assert_match /success/, flash[:notice] 195 | end 196 | 197 | def test_should_test 198 | put :test, params: { 199 | id: @ldap_setting.id, 200 | format: 'text', 201 | ldap_setting: @ldap_setting.send(:attributes), 202 | ldap_test: { test_users: 'example1', test_groups: 'Therß' } 203 | } 204 | 205 | assert_response :success 206 | assert_equal 'text/plain', response.content_type 207 | 208 | assert_match /User \"example1\":/, response.body 209 | assert_match /Group \"Therß\":/, response.body 210 | assert_match /Users enabled:/, response.body 211 | assert_match /Users locked by flag:/, response.body 212 | assert_match /Admin users:/, response.body 213 | assert_match /Groups:/, response.body 214 | assert_match /LDAP attributes on a user:/, response.body 215 | assert_match /LDAP attributes on a group:/, response.body 216 | 217 | assert_no_match /ldap_test\.rb/, response.body, 'Should not throw an error' 218 | end 219 | 220 | def test_should_validate_on_test 221 | @ldap_setting.dyngroups = 'invalid' 222 | 223 | put :test, params: { 224 | id: @ldap_setting.id, 225 | format: 'text', 226 | ldap_setting: @ldap_setting.send(:attributes), 227 | ldap_test: { :test_users => 'example1', :test_groups => 'Therß' } 228 | } 229 | 230 | assert_response :success 231 | assert_equal 'text/plain', response.content_type 232 | 233 | assert_match /Validation errors .* Dynamic groups/m, response.body 234 | 235 | assert_no_match /ldap_test\.rb/, response.body, 'Should not throw an error' 236 | end 237 | end -------------------------------------------------------------------------------- /test/integration/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tainewoo/redmine_ldap_sync/95219d5f0ab007db9975a6d0f8e32e78c1f36728/test/integration/.gitkeep -------------------------------------------------------------------------------- /test/performance/auth_source_ldap_performance_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../../test_helper', __FILE__) 19 | require 'rails/performance_test_help' 20 | 21 | class AuthSourceLdapPerformanceTest < ActionDispatch::PerformanceTest 22 | fixtures :auth_sources, :users, :groups_users, :settings, :custom_fields 23 | fixtures :email_addresses if Redmine::VERSION::MAJOR >= 3 24 | 25 | setup do 26 | clear_ldap_cache! 27 | Setting.clear_cache 28 | @auth_source = auth_sources(:auth_sources_001) 29 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@auth_source.id) 30 | 31 | AuthSourceLdap.activate_users = false 32 | AuthSourceLdap.running_rake = false 33 | end 34 | 35 | def test_sync_groups 36 | @auth_source.sync_groups 37 | end 38 | 39 | def test_sync_users 40 | @auth_source.sync_users 41 | end 42 | end -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | 19 | if RUBY_VERSION >= '2.0.0' 20 | require 'simplecov' 21 | 22 | SimpleCov.start do 23 | add_group 'Controllers', 'app/controllers' 24 | add_group 'Models', 'app/models' 25 | add_group 'Helpers', 'app/helpers' 26 | add_group 'Libraries', 'lib' 27 | add_filter '/test/' 28 | add_filter 'init.rb' 29 | root File.expand_path(File.dirname(__FILE__) + '/../') 30 | end 31 | end 32 | 33 | require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper') 34 | 35 | Rails.backtrace_cleaner.remove_silencers! 36 | 37 | class ActiveSupport::TestCase 38 | self.fixture_path = File.expand_path(File.dirname(__FILE__) + '/fixtures') 39 | 40 | def clear_ldap_cache! 41 | FileUtils.rm_rf Rails.root.join("tmp/ldap_cache") 42 | end 43 | end 44 | 45 | class ActionDispatch::IntegrationTest 46 | self.fixture_path = File.expand_path(File.dirname(__FILE__) + '/fixtures') 47 | end 48 | 49 | module ActionController::TestCase::Behavior 50 | def process_patched(action, method, *args) 51 | options = args.extract_options! 52 | if options.present? 53 | params = options.delete(:params) 54 | options = options.merge(params) if params.present? 55 | args << options 56 | end 57 | process_unpatched(action, method, *args) 58 | end 59 | 60 | if Rails::VERSION::MAJOR < 5 61 | alias_method :process_unpatched, :process 62 | alias_method :process, :process_patched 63 | end 64 | end -------------------------------------------------------------------------------- /test/ui/base.rb: -------------------------------------------------------------------------------- 1 | # Redmine - project management software 2 | # Copyright (C) 2006-2017 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 | require 'capybara/rails' 20 | 21 | Capybara.default_driver = :selenium 22 | Capybara.register_driver :selenium do |app| 23 | # Use the following driver definition to test locally using Chrome 24 | # (also requires chromedriver to be in PATH) 25 | # Capybara::Selenium::Driver.new(app, :browser => :chrome) 26 | # Add :switches => %w[--lang=en] to force default browser locale to English 27 | # Default for Selenium remote driver is to connect to local host on port 4444 28 | # This can be change using :url => 'http://localhost:9195' if necessary 29 | # PhantomJS 1.8 now directly supports Webdriver Wire API, 30 | # simply run it with `phantomjs --webdriver 4444` 31 | # Add :desired_capabilities => Selenium::WebDriver::Remote::Capabilities.internet_explorer) 32 | # to run on Selenium Grid Hub with IE 33 | Capybara::Selenium::Driver.new(app, browser: :remote, desired_capabilities: Selenium::WebDriver::Remote::Capabilities.phantomjs) 34 | end 35 | 36 | Capybara.register_driver :chrome_headless do |app| 37 | capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( 38 | chromeOptions: { args: %w(headless disable-popup-blocking no-sandbox disable-gpu window-size=1024,900 lang=en) } 39 | ) 40 | Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities ) 41 | end 42 | 43 | # default: 2 44 | Capybara.default_wait_time = 2 45 | 46 | module Redmine 47 | module UiTest 48 | # Base class for UI tests 49 | class Base < ActionDispatch::IntegrationTest 50 | include Capybara::DSL 51 | 52 | # Stop ActiveRecord from wrapping tests in transactions 53 | # Transactional fixtures do not work with Selenium tests, because Capybara 54 | # uses a separate server thread, which the transactions would be hidden 55 | if defined? self.use_transactional_tests 56 | self.use_transactional_tests = false 57 | else 58 | self.use_transactional_fixtures = false 59 | end 60 | 61 | # Should not depend on locale since Redmine displays login page 62 | # using default browser locale which depend on system locale for "real" browsers drivers 63 | def log_user(login, password) 64 | visit '/my/page' 65 | assert_equal '/login', current_path 66 | within('#login-form form') do 67 | fill_in 'username', :with => login 68 | fill_in 'password', :with => password 69 | find('input[name=login]').click 70 | end 71 | assert_equal '/my/page', current_path 72 | end 73 | 74 | setup do 75 | # Set the page width higher than 900 to get the full layout with sidebar 76 | page.driver.browser.manage.window.resize_to(1024, 900) 77 | end 78 | 79 | teardown do 80 | Capybara.reset_sessions! # Forget the (simulated) browser state 81 | Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver 82 | end 83 | end 84 | end 85 | end -------------------------------------------------------------------------------- /test/ui/ldap_setting_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../base', __FILE__) 19 | 20 | if RUBY_VERSION >= '2.0.0' 21 | require 'simplecov' 22 | SimpleCov.command_name 'UI Tests' 23 | end 24 | 25 | class Redmine::UiTest::LdapSettingTest < Redmine::UiTest::Base 26 | fixtures :auth_sources, :users, :settings, :custom_fields 27 | fixtures :email_addresses if Redmine::VERSION::MAJOR >= 3 28 | 29 | setup do 30 | log_user('admin', 'admin') 31 | visit '/admin/ldap_sync' 32 | within 'tr#ldap-config-1' do 33 | click_link 'LDAP test server' 34 | end 35 | assert_equal '/admin/ldap_sync/1/edit', current_path 36 | end 37 | 38 | def test_ldap_setting_test 39 | click_link 'Synchronization actions' 40 | select 'Enabled', :from => 'Dynamic groups' 41 | 42 | click_link 'Test' 43 | within 'div#tab-content-Test' do 44 | fill_in 'Users', :with => 'tweetmicro,systemhack,microunit,missing_user' 45 | fill_in 'Groups', :with => 'Iardum,Therß,MissingGroup' 46 | click_link 'Execute' 47 | end 48 | 49 | 50 | assert_selector '#test-result', :text => /User "tweetmicro":\s+Email = tweetmicro@fakemail.com/ 51 | assert_selector '#test-result', :text => /User "microunit":\s+Email = microunit@fakemail.com/ 52 | assert_selector '#test-result', :text => /User "missing_user": Not found/ 53 | 54 | assert_selector '#test-result', :text => /Group "Iardum": No fields/ 55 | assert_selector '#test-result', :text => /Group "Therß": Description = Therß Team Group/ 56 | assert_selector '#test-result', :text => /Group "MissingGroup": Not found/ 57 | 58 | assert_selector '#test-result', :text => /Users enabled: a total of \d+\s+\[[^\]]*"microunit"[^\]]*\]/ 59 | assert_selector '#test-result', :text => /Users locked by flag: a total of \d+\s+\[[^\]]*"tweetmicro"[^\]]*\]/ 60 | assert_selector '#test-result', :text => /Groups: a total of \d+\s+\[[^\]]*\]/ 61 | assert_selector '#test-result', :text => /Dynamic groups: a total of \d+\s+.*MicroUsers:\s+\[[^\]]*microunit[^\]]*\]/ 62 | end 63 | 64 | def test_base_settings 65 | select 'Samba LDAP', :from => 'Base settings' 66 | 67 | assert_equal 'sambaSamAccount', find_field('Users objectclass').value 68 | assert_equal 'member', find_field('Member users (group)').value 69 | 70 | select 'Active Directory (with nested groups)', :from => 'Base settings' 71 | 72 | assert_equal 'on_parents', find_field('Nested groups').value 73 | assert_equal 'flags.to_i & 2 != 0', find_field('Account disabled test').value 74 | assert_equal 'samaccountname', find_field('Group name (group)').value 75 | assert_equal 'useraccountcontrol', find_field('Account flags (user)').value 76 | assert_equal 'distinguishedname', find_field('Groupid (group)').value 77 | assert_equal 'member', find_field('Member groups (group)').value 78 | assert_equal 'distinguishedname', find_field('Memberid (group)').value 79 | end 80 | 81 | def test_group_membership 82 | select 'On the user class', :from => 'Group membership' 83 | 84 | assert !find_field('Member users (group)').visible? rescue Capybara::ElementNotFound 85 | assert !find_field('Memberid (user)').visible? rescue Capybara::ElementNotFound 86 | assert find_field('Groups (user)').visible? 87 | assert find_field('Groupid (group)').visible? 88 | 89 | select 'On the group class', :from => 'Group membership' 90 | 91 | assert !find_field('Groups (user)').visible? rescue Capybara::ElementNotFound 92 | assert !find_field('Groupid (group)').visible? rescue Capybara::ElementNotFound 93 | assert find_field('Member users (group)').visible? 94 | assert find_field('Memberid (user)').visible? 95 | end 96 | 97 | def test_nested_groups 98 | select 'Disabled', :from => 'Nested groups' 99 | 100 | assert !find_field('Member groups (group)').visible? rescue Capybara::ElementNotFound 101 | assert !find_field('Memberid (group)').visible? rescue Capybara::ElementNotFound 102 | assert !find_field('Parent groups (group)').visible? rescue Capybara::ElementNotFound 103 | assert !find_field('Parentid (group)').visible? rescue Capybara::ElementNotFound 104 | 105 | select 'Membership on the parent class', :from => 'Nested groups' 106 | 107 | assert !find_field('Parent groups (group)').visible? rescue Capybara::ElementNotFound 108 | assert !find_field('Parentid (group)').visible? rescue Capybara::ElementNotFound 109 | assert find_field('Member groups (group)').visible? 110 | assert find_field('Memberid (group)').visible? 111 | 112 | select 'Membership on the member class', :from => 'Nested groups' 113 | 114 | assert !find_field('Member groups (group)').visible? rescue Capybara::ElementNotFound 115 | assert !find_field('Memberid (group)').visible? rescue Capybara::ElementNotFound 116 | assert find_field('Parent groups (group)').visible? 117 | assert find_field('Parentid (group)').visible? 118 | end 119 | end -------------------------------------------------------------------------------- /test/ui/login_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../base', __FILE__) 19 | 20 | if RUBY_VERSION >= '2.0.0' 21 | require 'simplecov' 22 | SimpleCov.command_name 'UI Tests' 23 | end 24 | 25 | class Redmine::UiTest::LoginTest < Redmine::UiTest::Base 26 | fixtures :auth_sources, :users, :settings, :custom_fields, :roles, :projects, :members, :member_roles 27 | fixtures :email_addresses if Redmine::VERSION::MAJOR >= 3 28 | 29 | setup do 30 | visit '/login' 31 | end 32 | 33 | def test_login_with_existing_user 34 | within '#login-form' do 35 | fill_in 'Login', :with => 'loadgeek' 36 | fill_in 'Password', :with => 'password' 37 | click_on 'Login' 38 | end 39 | assert_equal my_page_path, current_path 40 | end 41 | 42 | def test_login_with_new_user 43 | within '#login-form' do 44 | fill_in 'Login', :with => 'systemhack' 45 | fill_in 'Password', :with => 'password' 46 | click_on 'Login' 47 | end 48 | assert_equal my_page_path, current_path 49 | end 50 | 51 | def test_login_with_incomplete_user 52 | within '#login-form' do 53 | fill_in 'Login', :with => 'incomplete' 54 | fill_in 'Password', :with => 'password' 55 | click_on 'Login' 56 | end 57 | 58 | assert_selector 'h2', :text => /Register/ 59 | 60 | fill_in 'First name', :with => 'Incomplete' 61 | fill_in 'Last name', :with => 'User' 62 | fill_in 'Email', :with => 'incomplete@fakemail.com' 63 | select 'Nederlands', :from => 'Language' 64 | 65 | click_on 'Submit' 66 | 67 | assert_equal my_account_path, current_path 68 | 69 | assert User.find_by_login('incomplete') 70 | end 71 | 72 | end -------------------------------------------------------------------------------- /test/unit/helpers/ldap_settings_helper_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../../../test_helper', __FILE__) 19 | 20 | class LdapSettingsHelperTest < ActionView::TestCase 21 | include LdapSettingsHelper 22 | include Redmine::I18n 23 | 24 | fixtures :auth_sources, :settings, :custom_fields 25 | 26 | setup do 27 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(auth_sources(:auth_sources_001).id) 28 | end 29 | 30 | def test_groups_fields 31 | assert_equal ['Description'], group_fields.map(&:name) 32 | assert_equal ['no description'], group_fields.map(&:default_value) 33 | assert_equal ['description'], group_fields.map(&:ldap_attribute) 34 | 35 | @ldap_setting.group_ldap_attrs = {} 36 | assert_equal [''], group_fields.map(&:ldap_attribute) 37 | end 38 | 39 | def test_user_fields 40 | assert_equal ['Email', 'First name', 'Last name', 'Preferred Language', 'Uid Number'], user_fields.map(&:name).sort 41 | assert_equal ['', '', '', '0', 'en'], user_fields.map(&:default_value).sort 42 | assert_equal %w(givenName mail preferredLanguage sn uidNumber), user_fields.map(&:ldap_attribute).sort 43 | 44 | @ldap_setting.user_ldap_attrs = {} 45 | assert_equal ['', '', 'givenName', 'mail', 'sn'], user_fields.map(&:ldap_attribute).sort 46 | end 47 | 48 | def test_users_fields_list 49 | fields = [ 50 | ["3", "Test Group"] 51 | ] 52 | 53 | assert_equal " Description = Test Group\n", group_fields_list(fields) 54 | end 55 | 56 | def test_groups_fields_list 57 | fields = [ 58 | ["1", "de"], 59 | ["2", "67123"] 60 | ] 61 | group_changes = {:added => ["group1", "group2"]} 62 | 63 | assert_equal " Preferred Language = de\n" + 64 | " Uid Number = 67123\n" + 65 | " Groups = [\"group1\", \"group2\"]\n", 66 | user_fields_list(fields, group_changes) 67 | end 68 | 69 | def test_options_for_base_settings 70 | assert_not_equal 0, options_for_base_settings.size 71 | end 72 | 73 | def test_user_field_name 74 | assert_equal 'Preferred Language', user_field_name("1") 75 | end 76 | 77 | def test_group_field_name 78 | assert_equal 'Description', group_field_name("3") 79 | end 80 | 81 | def test_change_status_link 82 | @ldap_setting.active = true 83 | assert_match /Disable/, change_status_link(@ldap_setting) 84 | 85 | @ldap_setting.active = false 86 | assert_match /Enable/, change_status_link(@ldap_setting) 87 | end 88 | end -------------------------------------------------------------------------------- /test/unit/ldap_test_test.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Copyright (C) 2011-2013 The Redmine LDAP Sync Authors 3 | # 4 | # This file is part of Redmine LDAP Sync. 5 | # 6 | # Redmine LDAP Sync is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Redmine LDAP Sync is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Redmine LDAP Sync. If not, see . 18 | require File.expand_path('../../test_helper', __FILE__) 19 | 20 | class LdapTestTest < ActiveSupport::TestCase 21 | include ActiveModel::Lint::Tests 22 | 23 | fixtures :auth_sources, :users, :groups_users, :settings, :custom_fields 24 | fixtures :email_addresses if Redmine::VERSION::MAJOR >= 3 25 | 26 | setup do 27 | Setting.clear_cache 28 | @auth_source = auth_sources(:auth_sources_001) 29 | @ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@auth_source.id) 30 | @ldap_test = @model = LdapTest.new(@ldap_setting) 31 | end 32 | 33 | def test_run_with_disabled_settings 34 | @ldap_setting.active = false; 35 | @ldap_test = LdapTest.new(@ldap_setting) 36 | 37 | assert @ldap_test.setting.active? 38 | 39 | @ldap_test.run_with_users_and_groups([], []) 40 | assert_not_equal 0, @ldap_test.non_dynamic_groups.size 41 | 42 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 43 | end 44 | 45 | def test_run_with_one_or_more_users 46 | @ldap_test.run_with_users_and_groups(['loadgeek'], []) 47 | assert_equal 1, @ldap_test.users_at_ldap.size 48 | assert_include 'loadgeek', @ldap_test.users_at_ldap.keys 49 | 50 | @ldap_test = LdapTest.new(@ldap_setting) 51 | @ldap_test.run_with_users_and_groups(['MissingUser', 'tweetmicro'], []) 52 | assert_equal 2, @ldap_test.users_at_ldap.size 53 | assert_include 'MissingUser', @ldap_test.users_at_ldap.keys 54 | assert_equal :not_found, @ldap_test.users_at_ldap['MissingUser'] 55 | assert_include 'tweetmicro', @ldap_test.users_at_ldap.keys 56 | assert_not_equal 0, @ldap_test.users_at_ldap['tweetmicro'][:groups][:added].size 57 | assert_equal 5, @ldap_test.users_at_ldap['tweetmicro'][:fields].size, "#{@ldap_test.users_at_ldap['tweetmicro'][:fields]}" 58 | assert_equal 0, @ldap_test.groups_at_ldap.size 59 | 60 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 61 | end 62 | 63 | def test_run_with_one_or_more_groups 64 | @ldap_test.run_with_users_and_groups([], ['Rynever']) 65 | assert_equal 1, @ldap_test.groups_at_ldap.size 66 | assert_include 'Rynever', @ldap_test.groups_at_ldap.keys 67 | 68 | @ldap_test = LdapTest.new(@ldap_setting) 69 | @ldap_test.run_with_users_and_groups([], ['MissingGroup', 'Therß']) 70 | assert_equal 2, @ldap_test.groups_at_ldap.size 71 | assert_include 'MissingGroup', @ldap_test.groups_at_ldap.keys 72 | assert_equal :not_found, @ldap_test.groups_at_ldap['MissingGroup'] 73 | assert_include 'Therß', @ldap_test.groups_at_ldap.keys 74 | assert_equal 1, @ldap_test.groups_at_ldap['Therß'][:fields].size 75 | assert_equal 0, @ldap_test.users_at_ldap.size 76 | 77 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 78 | end 79 | 80 | def test_run_with_users_and_groups 81 | @ldap_test.run_with_users_and_groups(['tweetsave', 'microunit'], ['Briklør', 'Rynever', 'Worathest']) 82 | assert_equal 2, @ldap_test.users_at_ldap.size 83 | assert_equal 3, @ldap_test.groups_at_ldap.size 84 | 85 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 86 | end 87 | 88 | def test_run_with_no_group_fields_and_user_fields 89 | @ldap_setting.group_fields_to_sync = [] 90 | @ldap_setting.user_fields_to_sync = [] 91 | 92 | @ldap_test.run_with_users_and_groups(['tweetsave'], ['Briklør', 'Therß']) 93 | assert_equal 0, @ldap_test.groups_at_ldap['Therß'][:fields].size 94 | 95 | # uid is required and should be set with the default value 96 | assert_equal 4, @ldap_test.users_at_ldap['tweetsave'][:fields].size, "#{@ldap_test.users_at_ldap['tweetsave'][:fields]}" 97 | 98 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 99 | end 100 | 101 | def test_run_with_deleted_users 102 | @ldap_test.run_with_users_and_groups(['tweetsave'], ['Briklør']) 103 | assert_not_equal 0, @ldap_test.user_changes[:locked].size 104 | assert_not_equal 0, @ldap_test.user_changes[:deleted].size 105 | 106 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 107 | end 108 | 109 | def test_run_with_admin_group 110 | @ldap_setting.admin_group = 'Worathest' 111 | 112 | @ldap_test.run_with_users_and_groups(['tweetsave'], ['Therß']) 113 | assert_not_equal 0, @ldap_test.admin_users.size 114 | 115 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 116 | end 117 | 118 | def test_run_with_required_group 119 | @ldap_setting.required_group = 'Bluil' 120 | 121 | @ldap_test.run_with_users_and_groups(['tweetsave'], ['Therß']) 122 | assert_not_equal 0, @ldap_test.users_locked_by_group.size 123 | 124 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 125 | end 126 | 127 | def test_run_with_dynamic_groups 128 | @ldap_setting.dyngroups = 'enabled' 129 | 130 | @ldap_test.run_with_users_and_groups(['microunit'], ['Enden']) 131 | assert_include 'MicroUsers', @ldap_test.users_at_ldap['microunit'][:groups][:added] 132 | assert_not_equal 0, @ldap_test.dynamic_groups.size 133 | 134 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 135 | end 136 | 137 | def test_run_with_minimal_settings 138 | @ldap_setting.dyngroups = '' 139 | @ldap_setting.nested_groups = '' 140 | @ldap_setting.sync_on_login = '' 141 | @ldap_setting.account_flags = '' 142 | @ldap_setting.group_fields_to_sync = [] 143 | @ldap_setting.user_fields_to_sync = [] 144 | @ldap_setting.admin_group = '' 145 | @ldap_setting.required_group = '' 146 | 147 | @ldap_test.run_with_users_and_groups([], []) 148 | assert_not_equal 0, @ldap_test.messages.size 149 | assert_not_equal 0, @ldap_test.user_changes[:enabled].size 150 | assert_equal 0, @ldap_test.user_changes[:locked].size 151 | assert_equal 1, @ldap_test.user_changes[:deleted].size 152 | assert_equal 0, @ldap_test.users_at_ldap.size 153 | assert_equal 0, @ldap_test.groups_at_ldap.size 154 | assert_not_equal 0, @ldap_test.non_dynamic_groups.size 155 | assert_equal 0, @ldap_test.dynamic_groups.size 156 | assert_equal 0, @ldap_test.users_locked_by_group.size 157 | assert_equal 0, @ldap_test.admin_users.size 158 | 159 | assert_no_match /ldap_test\.rb/, @ldap_test.messages, "Should not throw an error" 160 | end 161 | 162 | def test_run_without_groups_base_dn_should_fail_on_open_ldap 163 | @ldap_setting.groups_base_dn = '' 164 | 165 | @ldap_test.run_with_users_and_groups([], []) 166 | assert_not_equal 0, @ldap_test.messages.size 167 | assert_equal 0, @ldap_test.non_dynamic_groups.size 168 | assert_equal 0, @ldap_test.dynamic_groups.size 169 | 170 | assert_match /ldap_test\.rb/, @ldap_test.messages, "Should throw an error" 171 | end 172 | 173 | def test_run_with_dynamic_bind_should_not_fail 174 | @auth_source.account = 'uid=$login,ou=Person,dc=redmine,dc=org' 175 | assert @auth_source.save, @auth_source.errors.full_messages.join(', ') 176 | ldap_setting = LdapSetting.find_by_auth_source_ldap_id(@auth_source.id) 177 | ldap_test = LdapTest.new(ldap_setting) 178 | 179 | ldap_test.bind_user = 'admin' 180 | ldap_test.bind_password = 'password' 181 | ldap_test.run_with_users_and_groups([], []) 182 | assert_not_equal 15, ldap_test.messages.size 183 | assert_equal 15, ldap_test.non_dynamic_groups.size 184 | 185 | assert_no_match /ldap_test\.rb/, ldap_test.messages, "Should no throw an error" 186 | end 187 | 188 | def test_log_messages 189 | @ldap_test.run_with_users_and_groups([], []) 190 | assert_match /active, .* locked .* deleted/, @ldap_test.messages 191 | end 192 | 193 | def test_error_case 194 | @ldap_setting.account_locked_test = "flags.include? [disabled]'" 195 | 196 | @ldap_test.run_with_users_and_groups([], []) 197 | 198 | assert_match /ldap_test\.rb/, @ldap_test.messages, "Should throw an error" 199 | end 200 | 201 | def test_should_filter_the_list_of_groups_with_the_groupname_pattern 202 | @ldap_setting.groupname_pattern = "s$" 203 | @ldap_setting.dyngroups = 'enabled' 204 | 205 | @ldap_test.run_with_users_and_groups([], []) 206 | 207 | assert_equal 3, @ldap_test.non_dynamic_groups.size + @ldap_test.dynamic_groups.size 208 | assert_include 'Säyeldas', @ldap_test.non_dynamic_groups 209 | end 210 | 211 | end --------------------------------------------------------------------------------