activeldap 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. data/CHANGES +454 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +58 -0
  4. data/README +101 -0
  5. data/Rakefile +175 -0
  6. data/TODO +25 -0
  7. data/benchmark/bench-al.rb +202 -0
  8. data/benchmark/config.yaml.sample +5 -0
  9. data/data/locale/en/LC_MESSAGES/active-ldap.mo +0 -0
  10. data/data/locale/ja/LC_MESSAGES/active-ldap.mo +0 -0
  11. data/examples/al-admin/README +182 -0
  12. data/examples/al-admin/Rakefile +10 -0
  13. data/examples/al-admin/app/controllers/account_controller.rb +59 -0
  14. data/examples/al-admin/app/controllers/application.rb +34 -0
  15. data/examples/al-admin/app/controllers/attributes_controller.rb +17 -0
  16. data/examples/al-admin/app/controllers/directory_controller.rb +47 -0
  17. data/examples/al-admin/app/controllers/object_classes_controller.rb +17 -0
  18. data/examples/al-admin/app/controllers/syntaxes_controller.rb +17 -0
  19. data/examples/al-admin/app/controllers/users_controller.rb +51 -0
  20. data/examples/al-admin/app/controllers/welcome_controller.rb +10 -0
  21. data/examples/al-admin/app/helpers/account_helper.rb +2 -0
  22. data/examples/al-admin/app/helpers/application_helper.rb +42 -0
  23. data/examples/al-admin/app/helpers/attributes_helper.rb +15 -0
  24. data/examples/al-admin/app/helpers/directory_helper.rb +7 -0
  25. data/examples/al-admin/app/helpers/object_classes_helper.rb +10 -0
  26. data/examples/al-admin/app/helpers/syntaxes_helper.rb +10 -0
  27. data/examples/al-admin/app/helpers/url_helper.rb +13 -0
  28. data/examples/al-admin/app/helpers/users_helper.rb +17 -0
  29. data/examples/al-admin/app/helpers/welcome_helper.rb +2 -0
  30. data/examples/al-admin/app/models/entry.rb +23 -0
  31. data/examples/al-admin/app/models/ldap_user.rb +54 -0
  32. data/examples/al-admin/app/models/user.rb +91 -0
  33. data/examples/al-admin/app/views/_entry/_attributes_information.rhtml +23 -0
  34. data/examples/al-admin/app/views/_entry/_entry.rhtml +15 -0
  35. data/examples/al-admin/app/views/_schema/_aliases.rhtml +7 -0
  36. data/examples/al-admin/app/views/_switcher/_after.rhtml +2 -0
  37. data/examples/al-admin/app/views/_switcher/_before.rhtml +5 -0
  38. data/examples/al-admin/app/views/account/login.rhtml +26 -0
  39. data/examples/al-admin/app/views/account/sign_up.rhtml +28 -0
  40. data/examples/al-admin/app/views/attributes/_attributes.rhtml +19 -0
  41. data/examples/al-admin/app/views/attributes/_detail.rhtml +29 -0
  42. data/examples/al-admin/app/views/attributes/index.rhtml +3 -0
  43. data/examples/al-admin/app/views/attributes/show.rhtml +31 -0
  44. data/examples/al-admin/app/views/directory/_tree.rhtml +10 -0
  45. data/examples/al-admin/app/views/directory/_tree_view_js.rhtml +26 -0
  46. data/examples/al-admin/app/views/directory/index.rhtml +13 -0
  47. data/examples/al-admin/app/views/directory/populate.rhtml +2 -0
  48. data/examples/al-admin/app/views/layouts/_flash_box.rhtml +4 -0
  49. data/examples/al-admin/app/views/layouts/_footer.rhtml +9 -0
  50. data/examples/al-admin/app/views/layouts/_header_menu.rhtml +10 -0
  51. data/examples/al-admin/app/views/layouts/_main_menu.rhtml +18 -0
  52. data/examples/al-admin/app/views/layouts/application.rhtml +56 -0
  53. data/examples/al-admin/app/views/object_classes/_attributes.rhtml +28 -0
  54. data/examples/al-admin/app/views/object_classes/_object_classes.rhtml +19 -0
  55. data/examples/al-admin/app/views/object_classes/index.rhtml +3 -0
  56. data/examples/al-admin/app/views/object_classes/show.rhtml +39 -0
  57. data/examples/al-admin/app/views/syntaxes/_detail.rhtml +14 -0
  58. data/examples/al-admin/app/views/syntaxes/_syntaxes.rhtml +19 -0
  59. data/examples/al-admin/app/views/syntaxes/index.rhtml +3 -0
  60. data/examples/al-admin/app/views/syntaxes/show.rhtml +22 -0
  61. data/examples/al-admin/app/views/users/_attributes_update_form.rhtml +30 -0
  62. data/examples/al-admin/app/views/users/_form.rhtml +13 -0
  63. data/examples/al-admin/app/views/users/_object_classes_update_form.rhtml +40 -0
  64. data/examples/al-admin/app/views/users/_password_change_form.rhtml +20 -0
  65. data/examples/al-admin/app/views/users/edit.rhtml +15 -0
  66. data/examples/al-admin/app/views/users/index.rhtml +10 -0
  67. data/examples/al-admin/app/views/users/show.rhtml +11 -0
  68. data/examples/al-admin/app/views/welcome/index.rhtml +13 -0
  69. data/examples/al-admin/config/boot.rb +45 -0
  70. data/examples/al-admin/config/database.yml.example +19 -0
  71. data/examples/al-admin/config/environment.rb +70 -0
  72. data/examples/al-admin/config/environments/development.rb +21 -0
  73. data/examples/al-admin/config/environments/production.rb +18 -0
  74. data/examples/al-admin/config/environments/test.rb +19 -0
  75. data/examples/al-admin/config/ldap.yml.example +21 -0
  76. data/examples/al-admin/config/routes.rb +46 -0
  77. data/examples/al-admin/db/migrate/001_create_users.rb +16 -0
  78. data/examples/al-admin/lib/accept_http_rails_relative_url_root.rb +9 -0
  79. data/examples/al-admin/lib/authenticated_system.rb +124 -0
  80. data/examples/al-admin/lib/authenticated_test_helper.rb +113 -0
  81. data/examples/al-admin/lib/tasks/gettext.rake +35 -0
  82. data/examples/al-admin/po/en/al-admin.po +341 -0
  83. data/examples/al-admin/po/ja/al-admin.po +341 -0
  84. data/examples/al-admin/po/nl/al-admin.po +373 -0
  85. data/examples/al-admin/public/.htaccess +40 -0
  86. data/examples/al-admin/public/404.html +30 -0
  87. data/examples/al-admin/public/500.html +30 -0
  88. data/examples/al-admin/public/dispatch.cgi +10 -0
  89. data/examples/al-admin/public/dispatch.fcgi +24 -0
  90. data/examples/al-admin/public/dispatch.rb +10 -0
  91. data/examples/al-admin/public/favicon.ico +0 -0
  92. data/examples/al-admin/public/images/active-ldap.svg +6351 -0
  93. data/examples/al-admin/public/images/al-admin.png +0 -0
  94. data/examples/al-admin/public/images/al-admin.svg +6371 -0
  95. data/examples/al-admin/public/images/header-background.png +0 -0
  96. data/examples/al-admin/public/images/header-background.svg +99 -0
  97. data/examples/al-admin/public/images/rails.png +0 -0
  98. data/examples/al-admin/public/images/spinelz/accordion_tab_left_active.gif +0 -0
  99. data/examples/al-admin/public/images/spinelz/accordion_tab_left_inactive.gif +0 -0
  100. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_active.gif +0 -0
  101. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_inactive.gif +0 -0
  102. data/examples/al-admin/public/images/spinelz/accordion_tab_right_active.gif +0 -0
  103. data/examples/al-admin/public/images/spinelz/accordion_tab_right_inactive.gif +0 -0
  104. data/examples/al-admin/public/images/spinelz/balloon_back.gif +0 -0
  105. data/examples/al-admin/public/images/spinelz/balloon_bottom_left.gif +0 -0
  106. data/examples/al-admin/public/images/spinelz/balloon_bottom_middle.gif +0 -0
  107. data/examples/al-admin/public/images/spinelz/balloon_bottom_right.gif +0 -0
  108. data/examples/al-admin/public/images/spinelz/balloon_left_down_arrow.gif +0 -0
  109. data/examples/al-admin/public/images/spinelz/balloon_left_up_arrow.gif +0 -0
  110. data/examples/al-admin/public/images/spinelz/balloon_middle_left.gif +0 -0
  111. data/examples/al-admin/public/images/spinelz/balloon_middle_right.gif +0 -0
  112. data/examples/al-admin/public/images/spinelz/balloon_right_down_arrow.gif +0 -0
  113. data/examples/al-admin/public/images/spinelz/balloon_right_up_arrow.gif +0 -0
  114. data/examples/al-admin/public/images/spinelz/balloon_top_left.gif +0 -0
  115. data/examples/al-admin/public/images/spinelz/balloon_top_middle.gif +0 -0
  116. data/examples/al-admin/public/images/spinelz/balloon_top_right.gif +0 -0
  117. data/examples/al-admin/public/images/spinelz/barchart_h.gif +0 -0
  118. data/examples/al-admin/public/images/spinelz/barchart_v.gif +0 -0
  119. data/examples/al-admin/public/images/spinelz/button.gif +0 -0
  120. data/examples/al-admin/public/images/spinelz/calendar_default_handler.gif +0 -0
  121. data/examples/al-admin/public/images/spinelz/calendar_delete.gif +0 -0
  122. data/examples/al-admin/public/images/spinelz/calendar_next.gif +0 -0
  123. data/examples/al-admin/public/images/spinelz/calendar_next_second.gif +0 -0
  124. data/examples/al-admin/public/images/spinelz/calendar_pre.gif +0 -0
  125. data/examples/al-admin/public/images/spinelz/calendar_pre_second.gif +0 -0
  126. data/examples/al-admin/public/images/spinelz/calendar_private_icon.gif +0 -0
  127. data/examples/al-admin/public/images/spinelz/calendar_schedule.gif +0 -0
  128. data/examples/al-admin/public/images/spinelz/calender_back.gif +0 -0
  129. data/examples/al-admin/public/images/spinelz/calender_back_second.gif +0 -0
  130. data/examples/al-admin/public/images/spinelz/datepicker2_back.gif +0 -0
  131. data/examples/al-admin/public/images/spinelz/datepicker2_back_second.gif +0 -0
  132. data/examples/al-admin/public/images/spinelz/datepicker2_next.gif +0 -0
  133. data/examples/al-admin/public/images/spinelz/datepicker2_next_second.gif +0 -0
  134. data/examples/al-admin/public/images/spinelz/datepicker2_pre.gif +0 -0
  135. data/examples/al-admin/public/images/spinelz/datepicker2_pre_second.gif +0 -0
  136. data/examples/al-admin/public/images/spinelz/datepicker_back.gif +0 -0
  137. data/examples/al-admin/public/images/spinelz/datepicker_back_second.gif +0 -0
  138. data/examples/al-admin/public/images/spinelz/datepicker_next.gif +0 -0
  139. data/examples/al-admin/public/images/spinelz/datepicker_next_second.gif +0 -0
  140. data/examples/al-admin/public/images/spinelz/datepicker_pre.gif +0 -0
  141. data/examples/al-admin/public/images/spinelz/datepicker_pre_second.gif +0 -0
  142. data/examples/al-admin/public/images/spinelz/grid_down.gif +0 -0
  143. data/examples/al-admin/public/images/spinelz/grid_state.gif +0 -0
  144. data/examples/al-admin/public/images/spinelz/grid_up.gif +0 -0
  145. data/examples/al-admin/public/images/spinelz/icon_day.gif +0 -0
  146. data/examples/al-admin/public/images/spinelz/icon_month.gif +0 -0
  147. data/examples/al-admin/public/images/spinelz/icon_week.gif +0 -0
  148. data/examples/al-admin/public/images/spinelz/menubar_back.gif +0 -0
  149. data/examples/al-admin/public/images/spinelz/menubar_subcontents_back.gif +0 -0
  150. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_active.gif +0 -0
  151. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_inactive.gif +0 -0
  152. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_active.gif +0 -0
  153. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_inactive.gif +0 -0
  154. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_active.gif +0 -0
  155. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_inactive.gif +0 -0
  156. data/examples/al-admin/public/images/spinelz/select_date.gif +0 -0
  157. data/examples/al-admin/public/images/spinelz/selectabletable_selected.gif +0 -0
  158. data/examples/al-admin/public/images/spinelz/sideBarBox_about.gif +0 -0
  159. data/examples/al-admin/public/images/spinelz/sideBarBox_menu.gif +0 -0
  160. data/examples/al-admin/public/images/spinelz/sideBarBox_sample.gif +0 -0
  161. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomActive.gif +0 -0
  162. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomInactive.gif +0 -0
  163. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive.gif +0 -0
  164. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive2.gif +0 -0
  165. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive.gif +0 -0
  166. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive2.gif +0 -0
  167. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopActive.gif +0 -0
  168. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopInactive.gif +0 -0
  169. data/examples/al-admin/public/images/spinelz/sideBarBox_tabbar.gif +0 -0
  170. data/examples/al-admin/public/images/spinelz/sortableTable_down.gif +0 -0
  171. data/examples/al-admin/public/images/spinelz/sortableTable_normal.gif +0 -0
  172. data/examples/al-admin/public/images/spinelz/sortableTable_up.gif +0 -0
  173. data/examples/al-admin/public/images/spinelz/switcher_close.gif +0 -0
  174. data/examples/al-admin/public/images/spinelz/switcher_open.gif +0 -0
  175. data/examples/al-admin/public/images/spinelz/tabBox_close.gif +0 -0
  176. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftActive.gif +0 -0
  177. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftInactive.gif +0 -0
  178. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleActive.gif +0 -0
  179. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleInactive.gif +0 -0
  180. data/examples/al-admin/public/images/spinelz/tabBox_tabRightActive.gif +0 -0
  181. data/examples/al-admin/public/images/spinelz/tabBox_tabRightInactive.gif +0 -0
  182. data/examples/al-admin/public/images/spinelz/tab_bar.gif +0 -0
  183. data/examples/al-admin/public/images/spinelz/table_back.gif +0 -0
  184. data/examples/al-admin/public/images/spinelz/timepicker_clock.gif +0 -0
  185. data/examples/al-admin/public/images/spinelz/toolbar_close.gif +0 -0
  186. data/examples/al-admin/public/images/spinelz/toolbar_left.gif +0 -0
  187. data/examples/al-admin/public/images/spinelz/toolbar_max.gif +0 -0
  188. data/examples/al-admin/public/images/spinelz/toolbar_middle.gif +0 -0
  189. data/examples/al-admin/public/images/spinelz/toolbar_min.gif +0 -0
  190. data/examples/al-admin/public/images/spinelz/toolbar_next.gif +0 -0
  191. data/examples/al-admin/public/images/spinelz/toolbar_right.gif +0 -0
  192. data/examples/al-admin/public/images/spinelz/treeview_dir.gif +0 -0
  193. data/examples/al-admin/public/images/spinelz/treeview_file.gif +0 -0
  194. data/examples/al-admin/public/images/spinelz/treeview_group.gif +0 -0
  195. data/examples/al-admin/public/images/spinelz/treeview_group_special.gif +0 -0
  196. data/examples/al-admin/public/images/spinelz/treeview_state.gif +0 -0
  197. data/examples/al-admin/public/images/spinelz/treeview_user.gif +0 -0
  198. data/examples/al-admin/public/images/spinelz/window_bottom_left.gif +0 -0
  199. data/examples/al-admin/public/images/spinelz/window_bottom_middle.gif +0 -0
  200. data/examples/al-admin/public/images/spinelz/window_bottom_right.gif +0 -0
  201. data/examples/al-admin/public/images/spinelz/window_close.gif +0 -0
  202. data/examples/al-admin/public/images/spinelz/window_max.gif +0 -0
  203. data/examples/al-admin/public/images/spinelz/window_middle_left.gif +0 -0
  204. data/examples/al-admin/public/images/spinelz/window_middle_right.gif +0 -0
  205. data/examples/al-admin/public/images/spinelz/window_min.gif +0 -0
  206. data/examples/al-admin/public/images/spinelz/window_top_left.gif +0 -0
  207. data/examples/al-admin/public/images/spinelz/window_top_middle.gif +0 -0
  208. data/examples/al-admin/public/images/spinelz/window_top_right.gif +0 -0
  209. data/examples/al-admin/public/javascripts/application.js +2 -0
  210. data/examples/al-admin/public/javascripts/controls.js +833 -0
  211. data/examples/al-admin/public/javascripts/dragdrop.js +942 -0
  212. data/examples/al-admin/public/javascripts/effects.js +1088 -0
  213. data/examples/al-admin/public/javascripts/prototype.js +2515 -0
  214. data/examples/al-admin/public/javascripts/spinelz/accordion.js +185 -0
  215. data/examples/al-admin/public/javascripts/spinelz/ajaxHistory.js +157 -0
  216. data/examples/al-admin/public/javascripts/spinelz/balloon.js +287 -0
  217. data/examples/al-admin/public/javascripts/spinelz/barchart.js +524 -0
  218. data/examples/al-admin/public/javascripts/spinelz/calendar.js +3012 -0
  219. data/examples/al-admin/public/javascripts/spinelz/colorpicker.js +128 -0
  220. data/examples/al-admin/public/javascripts/spinelz/datepicker.js +438 -0
  221. data/examples/al-admin/public/javascripts/spinelz/grid.js +1391 -0
  222. data/examples/al-admin/public/javascripts/spinelz/grid_resizeEx.js +100 -0
  223. data/examples/al-admin/public/javascripts/spinelz/grid_sortabletableEx.js +129 -0
  224. data/examples/al-admin/public/javascripts/spinelz/inplaceEditorEx.js +148 -0
  225. data/examples/al-admin/public/javascripts/spinelz/menubar.js +232 -0
  226. data/examples/al-admin/public/javascripts/spinelz/navPanel.js +170 -0
  227. data/examples/al-admin/public/javascripts/spinelz/selectableTable.js +433 -0
  228. data/examples/al-admin/public/javascripts/spinelz/sideBarBox.js +282 -0
  229. data/examples/al-admin/public/javascripts/spinelz/sideBarBox_effects.js +83 -0
  230. data/examples/al-admin/public/javascripts/spinelz/sortableTable.js +270 -0
  231. data/examples/al-admin/public/javascripts/spinelz/switcher.js +78 -0
  232. data/examples/al-admin/public/javascripts/spinelz/tabBox.js +469 -0
  233. data/examples/al-admin/public/javascripts/spinelz/timepicker.js +384 -0
  234. data/examples/al-admin/public/javascripts/spinelz/toolbar.js +152 -0
  235. data/examples/al-admin/public/javascripts/spinelz/treeview.js +703 -0
  236. data/examples/al-admin/public/javascripts/spinelz/window.js +641 -0
  237. data/examples/al-admin/public/javascripts/spinelz/window_resizeEx.js +130 -0
  238. data/examples/al-admin/public/javascripts/spinelz_lib/builder.js +131 -0
  239. data/examples/al-admin/public/javascripts/spinelz_lib/controls.js +835 -0
  240. data/examples/al-admin/public/javascripts/spinelz_lib/dragdrop.js +944 -0
  241. data/examples/al-admin/public/javascripts/spinelz_lib/effects.js +1090 -0
  242. data/examples/al-admin/public/javascripts/spinelz_lib/json.js +139 -0
  243. data/examples/al-admin/public/javascripts/spinelz_lib/prototype.js +2515 -0
  244. data/examples/al-admin/public/javascripts/spinelz_lib/resize.js +215 -0
  245. data/examples/al-admin/public/javascripts/spinelz_lib/scriptaculous.js +51 -0
  246. data/examples/al-admin/public/javascripts/spinelz_lib/slider.js +278 -0
  247. data/examples/al-admin/public/javascripts/spinelz_lib/spinelz_util.js +1266 -0
  248. data/examples/al-admin/public/javascripts/spinelz_lib/unittest.js +564 -0
  249. data/examples/al-admin/public/robots.txt +1 -0
  250. data/examples/al-admin/public/stylesheets/account.css +41 -0
  251. data/examples/al-admin/public/stylesheets/attributes.css +1 -0
  252. data/examples/al-admin/public/stylesheets/base.css +99 -0
  253. data/examples/al-admin/public/stylesheets/common.css +2 -0
  254. data/examples/al-admin/public/stylesheets/detail.css +36 -0
  255. data/examples/al-admin/public/stylesheets/directory.css +22 -0
  256. data/examples/al-admin/public/stylesheets/object-classes.css +6 -0
  257. data/examples/al-admin/public/stylesheets/rails.css +35 -0
  258. data/examples/al-admin/public/stylesheets/spinelz/accordion.css +59 -0
  259. data/examples/al-admin/public/stylesheets/spinelz/balloon.css +151 -0
  260. data/examples/al-admin/public/stylesheets/spinelz/calendar.css +564 -0
  261. data/examples/al-admin/public/stylesheets/spinelz/datepicker.css +175 -0
  262. data/examples/al-admin/public/stylesheets/spinelz/grid.css +137 -0
  263. data/examples/al-admin/public/stylesheets/spinelz/menubar.css +78 -0
  264. data/examples/al-admin/public/stylesheets/spinelz/modal.css +22 -0
  265. data/examples/al-admin/public/stylesheets/spinelz/navPanel.css +58 -0
  266. data/examples/al-admin/public/stylesheets/spinelz/selectableTable.css +28 -0
  267. data/examples/al-admin/public/stylesheets/spinelz/sideBarBox.css +82 -0
  268. data/examples/al-admin/public/stylesheets/spinelz/sortableTable.css +51 -0
  269. data/examples/al-admin/public/stylesheets/spinelz/switcher.css +23 -0
  270. data/examples/al-admin/public/stylesheets/spinelz/tabBox.css +94 -0
  271. data/examples/al-admin/public/stylesheets/spinelz/timepicker.css +508 -0
  272. data/examples/al-admin/public/stylesheets/spinelz/toolbar.css +82 -0
  273. data/examples/al-admin/public/stylesheets/spinelz/treeview.css +121 -0
  274. data/examples/al-admin/public/stylesheets/spinelz/window.css +140 -0
  275. data/examples/al-admin/public/stylesheets/structure.css +81 -0
  276. data/examples/al-admin/public/stylesheets/syntaxes.css +1 -0
  277. data/examples/al-admin/public/stylesheets/users.css +13 -0
  278. data/examples/al-admin/public/stylesheets/welcome.css +0 -0
  279. data/examples/al-admin/script/about +3 -0
  280. data/examples/al-admin/script/breakpointer +3 -0
  281. data/examples/al-admin/script/console +3 -0
  282. data/examples/al-admin/script/destroy +3 -0
  283. data/examples/al-admin/script/generate +3 -0
  284. data/examples/al-admin/script/performance/benchmarker +3 -0
  285. data/examples/al-admin/script/performance/profiler +3 -0
  286. data/examples/al-admin/script/plugin +3 -0
  287. data/examples/al-admin/script/process/inspector +3 -0
  288. data/examples/al-admin/script/process/reaper +3 -0
  289. data/examples/al-admin/script/process/spawner +3 -0
  290. data/examples/al-admin/script/runner +3 -0
  291. data/examples/al-admin/script/server +3 -0
  292. data/examples/al-admin/test/fixtures/users.yml +9 -0
  293. data/examples/al-admin/test/functional/account_controller_test.rb +24 -0
  294. data/examples/al-admin/test/functional/attributes_controller_test.rb +18 -0
  295. data/examples/al-admin/test/functional/directory_controller_test.rb +18 -0
  296. data/examples/al-admin/test/functional/object_classes_controller_test.rb +18 -0
  297. data/examples/al-admin/test/functional/syntaxes_controller_test.rb +18 -0
  298. data/examples/al-admin/test/functional/users_controller_test.rb +18 -0
  299. data/examples/al-admin/test/functional/welcome_controller_test.rb +18 -0
  300. data/examples/al-admin/test/run-test.sh +3 -0
  301. data/examples/al-admin/test/test_helper.rb +28 -0
  302. data/examples/al-admin/test/unit/user_test.rb +13 -0
  303. data/examples/al-admin/vendor/plugins/exception_notification/README +111 -0
  304. data/examples/al-admin/vendor/plugins/exception_notification/init.rb +1 -0
  305. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifiable.rb +99 -0
  306. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier.rb +67 -0
  307. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb +77 -0
  308. data/examples/al-admin/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb +61 -0
  309. data/examples/al-admin/vendor/plugins/exception_notification/test/test_helper.rb +7 -0
  310. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml +1 -0
  311. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml +7 -0
  312. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml +16 -0
  313. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml +3 -0
  314. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml +2 -0
  315. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml +3 -0
  316. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml +6 -0
  317. data/examples/config.yaml.example +5 -0
  318. data/examples/example.der +0 -0
  319. data/examples/example.jpg +0 -0
  320. data/examples/groupadd +41 -0
  321. data/examples/groupdel +35 -0
  322. data/examples/groupls +49 -0
  323. data/examples/groupmod +42 -0
  324. data/examples/lpasswd +55 -0
  325. data/examples/objects/group.rb +13 -0
  326. data/examples/objects/ou.rb +4 -0
  327. data/examples/objects/user.rb +20 -0
  328. data/examples/ouadd +38 -0
  329. data/examples/useradd +45 -0
  330. data/examples/useradd-binary +50 -0
  331. data/examples/userdel +34 -0
  332. data/examples/userls +50 -0
  333. data/examples/usermod +42 -0
  334. data/examples/usermod-binary-add +47 -0
  335. data/examples/usermod-binary-add-time +51 -0
  336. data/examples/usermod-binary-del +48 -0
  337. data/examples/usermod-lang-add +43 -0
  338. data/lib/active_ldap/acts/tree.rb +75 -0
  339. data/lib/active_ldap/adapter/base.rb +531 -0
  340. data/lib/active_ldap/adapter/ldap.rb +231 -0
  341. data/lib/active_ldap/adapter/ldap_ext.rb +69 -0
  342. data/lib/active_ldap/adapter/net_ldap.rb +292 -0
  343. data/lib/active_ldap/adapter/net_ldap_ext.rb +29 -0
  344. data/lib/active_ldap/association/belongs_to.rb +47 -0
  345. data/lib/active_ldap/association/belongs_to_many.rb +42 -0
  346. data/lib/active_ldap/association/children.rb +21 -0
  347. data/lib/active_ldap/association/collection.rb +83 -0
  348. data/lib/active_ldap/association/has_many.rb +31 -0
  349. data/lib/active_ldap/association/has_many_utils.rb +35 -0
  350. data/lib/active_ldap/association/has_many_wrap.rb +46 -0
  351. data/lib/active_ldap/association/proxy.rb +102 -0
  352. data/lib/active_ldap/associations.rb +172 -0
  353. data/lib/active_ldap/attributes.rb +211 -0
  354. data/lib/active_ldap/base.rb +1273 -0
  355. data/lib/active_ldap/callbacks.rb +19 -0
  356. data/lib/active_ldap/command.rb +49 -0
  357. data/lib/active_ldap/configuration.rb +147 -0
  358. data/lib/active_ldap/connection.rb +237 -0
  359. data/lib/active_ldap/distinguished_name.rb +251 -0
  360. data/lib/active_ldap/escape.rb +12 -0
  361. data/lib/active_ldap/get_text/parser.rb +159 -0
  362. data/lib/active_ldap/get_text.rb +8 -0
  363. data/lib/active_ldap/get_text_fallback.rb +53 -0
  364. data/lib/active_ldap/get_text_support.rb +26 -0
  365. data/lib/active_ldap/helper.rb +33 -0
  366. data/lib/active_ldap/human_readable.rb +112 -0
  367. data/lib/active_ldap/ldap_error.rb +74 -0
  368. data/lib/active_ldap/ldif.rb +52 -0
  369. data/lib/active_ldap/object_class.rb +93 -0
  370. data/lib/active_ldap/operations.rb +429 -0
  371. data/lib/active_ldap/populate.rb +44 -0
  372. data/lib/active_ldap/schema/syntaxes.rb +386 -0
  373. data/lib/active_ldap/schema.rb +530 -0
  374. data/lib/active_ldap/timeout.rb +75 -0
  375. data/lib/active_ldap/timeout_stub.rb +17 -0
  376. data/lib/active_ldap/user_password.rb +93 -0
  377. data/lib/active_ldap/validations.rb +171 -0
  378. data/lib/active_ldap.rb +982 -0
  379. data/po/en/active-ldap.po +3677 -0
  380. data/po/ja/active-ldap.po +3713 -0
  381. data/rails/plugin/active_ldap/README +54 -0
  382. data/rails/plugin/active_ldap/generators/model_active_ldap/USAGE +17 -0
  383. data/rails/plugin/active_ldap/generators/model_active_ldap/model_active_ldap_generator.rb +70 -0
  384. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/fixtures.yml +11 -0
  385. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
  386. data/rails/plugin/active_ldap/generators/model_active_ldap/templates/unit_test.rb +10 -0
  387. data/rails/plugin/active_ldap/generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
  388. data/rails/plugin/active_ldap/generators/scaffold_al/scaffold_al_generator.rb +20 -0
  389. data/rails/plugin/active_ldap/init.rb +26 -0
  390. data/test/al-test-utils.rb +362 -0
  391. data/test/command.rb +62 -0
  392. data/test/config.yaml.sample +6 -0
  393. data/test/run-test.rb +31 -0
  394. data/test/test-unit-ext/always-show-result.rb +28 -0
  395. data/test/test-unit-ext/backtrace-filter.rb +17 -0
  396. data/test/test-unit-ext/long-display-for-emacs.rb +25 -0
  397. data/test/test-unit-ext/priority.rb +163 -0
  398. data/test/test-unit-ext.rb +4 -0
  399. data/test/test_acts_as_tree.rb +57 -0
  400. data/test/test_adapter.rb +98 -0
  401. data/test/test_associations.rb +353 -0
  402. data/test/test_attributes.rb +79 -0
  403. data/test/test_base.rb +547 -0
  404. data/test/test_base_per_instance.rb +55 -0
  405. data/test/test_bind.rb +62 -0
  406. data/test/test_callback.rb +35 -0
  407. data/test/test_configuration.rb +40 -0
  408. data/test/test_connection.rb +59 -0
  409. data/test/test_connection_per_class.rb +58 -0
  410. data/test/test_connection_per_dn.rb +78 -0
  411. data/test/test_dn.rb +160 -0
  412. data/test/test_find.rb +96 -0
  413. data/test/test_groupadd.rb +50 -0
  414. data/test/test_groupdel.rb +46 -0
  415. data/test/test_groupls.rb +107 -0
  416. data/test/test_groupmod.rb +51 -0
  417. data/test/test_ldif.rb +35 -0
  418. data/test/test_lpasswd.rb +75 -0
  419. data/test/test_object_class.rb +56 -0
  420. data/test/test_reflection.rb +179 -0
  421. data/test/test_schema.rb +433 -0
  422. data/test/test_syntax.rb +329 -0
  423. data/test/test_user.rb +227 -0
  424. data/test/test_user_password.rb +93 -0
  425. data/test/test_useradd-binary.rb +61 -0
  426. data/test/test_useradd.rb +57 -0
  427. data/test/test_userdel.rb +48 -0
  428. data/test/test_userls.rb +91 -0
  429. data/test/test_usermod-binary-add-time.rb +64 -0
  430. data/test/test_usermod-binary-add.rb +63 -0
  431. data/test/test_usermod-binary-del.rb +66 -0
  432. data/test/test_usermod-lang-add.rb +59 -0
  433. data/test/test_usermod.rb +58 -0
  434. data/test/test_validation.rb +110 -0
  435. metadata +536 -0
@@ -0,0 +1,982 @@
1
+ #!/usr/bin/ruby
2
+ # = Ruby/ActiveLdap
3
+ #
4
+ # "Ruby/ActiveLdap" Copyright (C) 2004,2005 Will Drewry mailto:will@alum.bu.edu
5
+ #
6
+ # == Introduction
7
+ #
8
+ # Ruby/ActiveLdap is a novel way of interacting with LDAP. Most interaction with
9
+ # LDAP is done using clunky LDIFs, web interfaces, or with painful APIs that
10
+ # required a thick reference manual nearby. Ruby/ActiveLdap aims to fix that.
11
+ # Inspired by ActiveRecord[http://activerecord.rubyonrails.org], Ruby/ActiveLdap provides an
12
+ # object oriented interface to LDAP entries.
13
+ #
14
+ # The target audience is system administrators and LDAP users everywhere that
15
+ # need quick, clean access to LDAP in Ruby.
16
+ #
17
+ # === What's LDAP?
18
+ #
19
+ # LDAP stands for "Lightweight Directory Access Protocol." Basically this means
20
+ # that it is the protocol used for accessing LDAP servers. LDAP servers
21
+ # lightweight directories. An LDAP server can contain anything from a simple
22
+ # digital phonebook to user accounts for computer systems. More and more
23
+ # frequently, it is being used for the latter. My examples in this text will
24
+ # assume some familiarity with using LDAP as a centralized authentication and
25
+ # authorization server for Unix systems. (Unfortunately, I've yet to try this
26
+ # against Microsoft's ActiveDirectory, despite what the name implies.)
27
+ #
28
+ # Further reading:
29
+ # * RFC1777[http://www.faqs.org/rfcs/rfc1777.html] - Lightweight Directory Access Protocol
30
+ # * OpenLDAP[http://www.openldap.org]
31
+ #
32
+ # === So why use Ruby/ActiveLdap?
33
+ #
34
+ # Well if you like to fumble around in the dark, dank innards of LDAP, you can
35
+ # quit reading now. However, if you'd like a cleaner way to integrate LDAP in to
36
+ # your existing code, hopefully that's why you'll want to use Ruby/ActiveLdap.
37
+ #
38
+ # Using LDAP directly (even with the excellent Ruby/LDAP), leaves you bound to
39
+ # the world of the predefined LDAP API. While this API is important for many
40
+ # reasons, having to extract code out of LDAP search blocks and create huge
41
+ # arrays of LDAP.mod entries make code harder to read, less intuitive, and just
42
+ # less fun to write. Hopefully, Ruby/ActiveLdap will remedy all of these
43
+ # problems!
44
+ #
45
+ # == Getting Started
46
+ #
47
+ # Ruby/ActiveLdap does have some overhead when you get started. You must not
48
+ # only install the package and all of it's requirements, but you must also make
49
+ # customizations that will let it work in your environment.
50
+ #
51
+ # === Requirements
52
+ #
53
+ # * Ruby[http://www.ruby-lang.org] 1.8.x
54
+ # * Ruby/LDAP[http://ruby-ldap.sourceforge.net]
55
+ # * (Optional) Ruby/LDAP+GSSAPI[http://caliban.org/files/redhat/RPMS/i386/ruby-ldap-0.8.2-4.i386.rpm]
56
+ # * An LDAP server compatible with Ruby/LDAP: OpenLDAP[http://www.openldap.org], etc
57
+ # - Your LDAP server must allow root_dse queries to allow for schema queries
58
+ # * Examples also require: Ruby/Password[http://raa.ruby-lang.org/project/ruby-password/]
59
+ #
60
+ # === Installation
61
+ #
62
+ # Assuming all the requirements are installed, you can install by grabbing the latest tgz file from
63
+ # the download site[http://rubyforge.org/frs/?group_id=381].
64
+ #
65
+ # The following steps will get the Ruby/ActiveLdap installed in no time!
66
+ #
67
+ # $ tar -xzvf ruby-activeldap-current.tgz
68
+ # $ cd ruby-activeldap-VERSION
69
+ #
70
+ # Edit lib/active_ldap/configuration.rb replacing values to match what will work
71
+ # with your LDAP servers. Please note that those variables are required, but can
72
+ # be overridden in any program as detailed later in this document. Also make
73
+ # sure that "ROOT" stays all upcase.
74
+ #
75
+ # Now run:
76
+ #
77
+ # $ (as root) rake install
78
+ #
79
+ # Now as a quick test, you can run:
80
+ #
81
+ # $ irb
82
+ # irb> require 'active_ldap'
83
+ # => true
84
+ # irb> exit
85
+ #
86
+ # If the require returns false or an exception is raised, there has been a
87
+ # problem with the installation. You may need to customize what setup.rb does on
88
+ # install.
89
+ #
90
+ #
91
+ # === Customizations
92
+ #
93
+ # Now that Ruby/ActiveLdap is installed and working, we still have a few more
94
+ # steps to make it useful for programming.
95
+ #
96
+ # Let's say that you are writing a Ruby program for managing user and group
97
+ # accounts in LDAP. I will use this as the running example throughout the
98
+ # document.
99
+ #
100
+ # You will want to make a directory called 'ldapadmin' wherever is convenient. Under this directory,
101
+ # you'll want to make sure you have a 'lib' directory.
102
+ #
103
+ # $ cd ~
104
+ # $ mkdir ldapadmin
105
+ # $ cd ldapadmin
106
+ # $ mkdir lib
107
+ # $ cd lib
108
+ #
109
+ # The lib directory is where we'll be making customizations. You can, of course,
110
+ # make this changes somewhere in Ruby's default search path to make this
111
+ # accessible to every Ruby scripts. Enough of my babbling, I'm sure you'd like to
112
+ # know what we're going to put in lib/.
113
+ #
114
+ # We're going to put extension classes in there. What are extension classes you say . . .
115
+ #
116
+ #
117
+ # == Usage
118
+ #
119
+ # This section covers using Ruby/ActiveLdap from writing extension classes to
120
+ # writing applications that use them.
121
+ #
122
+ # Just to give a taste of what's to come, here is a quick example using irb:
123
+ #
124
+ # irb> require 'active_ldap'
125
+ #
126
+ # Here's an extension class that maps to the LDAP Group objects:
127
+ #
128
+ # irb> class Group < ActiveLdap::Base
129
+ # irb* ldap_mapping
130
+ # irb* end
131
+ #
132
+ # Here is the Group class in use:
133
+ #
134
+ # irb> all_groups = Group.find(:all, '*').collect {|group| group.cn}
135
+ # => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
136
+ #
137
+ # irb> group = Group.find("develop")
138
+ # => #<Group:0x..........>
139
+ #
140
+ # irb> group.members.collect {|member| member.uid}
141
+ # => ["drewry"]
142
+ #
143
+ # irb> group.cn
144
+ # => "develop"
145
+ #
146
+ # irb> group.gid_number
147
+ # => "1003"
148
+ #
149
+ # That's it! No let's get back in to it.
150
+ #
151
+ # === Extension Classes
152
+ #
153
+ # Extension classes are classes that are subclassed from ActiveLdap::Base. They
154
+ # are used to represent objects in your LDAP server abstractly.
155
+ #
156
+ # ==== Why do I need them?
157
+ #
158
+ # Extension classes are what make Ruby/ActiveLdap "active"! They do all the
159
+ # background work to make easy-to-use objects by mapping the LDAP object's
160
+ # attributes on to a Ruby class.
161
+ #
162
+ #
163
+ # ==== Special Methods
164
+ #
165
+ # I will briefly talk about each of the methods you can use when defining an
166
+ # extension class. In the above example, I only made one special method call
167
+ # inside the Group class. More than likely, you will want to more than that.
168
+ #
169
+ # ===== ldap_mapping
170
+ #
171
+ # ldap_mapping is the only required method to setup an extension class for use
172
+ # with Ruby/ActiveLdap. It must be called inside of a subclass as shown above.
173
+ #
174
+ # Below is a much more realistic Group class:
175
+ #
176
+ # class Group < ActiveLdap::Base
177
+ # ldap_mapping :dn_attribute => 'cn',
178
+ # :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
179
+ # :scope => :one
180
+ # end
181
+ #
182
+ # As you can see, this method is used for defining how this class maps in to LDAP. Let's say that
183
+ # my LDAP tree looks something like this:
184
+ #
185
+ # * dc=dataspill,dc=org
186
+ # |- ou=People,dc=dataspill,dc=org
187
+ # |+ ou=Groups,dc=dataspill,dc=org
188
+ # \
189
+ # |- cn=develop,ou=Groups,dc=dataspill,dc=org
190
+ # |- cn=root,ou=Groups,dc=dataspill,dc=org
191
+ # |- ...
192
+ #
193
+ # Under ou=People I store user objects, and under ou=Groups, I store group
194
+ # objects. What |ldap_mapping| has done is mapped the class in to the LDAP tree
195
+ # abstractly. With the given :dnattr and :prefix, it will only work for entries
196
+ # under ou=Groups,dc=dataspill,dc=org using the primary attribute 'cn' as the
197
+ # beginning of the distinguished name.
198
+ #
199
+ # Just for clarity, here's how the arguments map out:
200
+ #
201
+ # cn=develop,ou=Groups,dc=dataspill,dc=org
202
+ # ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
203
+ # :dn_attribute | |
204
+ # :prefix |
205
+ # :base from configuration.rb
206
+ #
207
+ # :scope tells ActiveLdap to only search under ou=Groups, and not to look deeper
208
+ # for dnattr matches. (e.g. cn=develop,ou=DevGroups,ou=Groups,dc=dataspill,dc=org)
209
+ #
210
+ # Something's missing: :classes. :classes is used to tell Ruby/ActiveLdap what
211
+ # the minimum requirement is when creating a new object. LDAP uses objectClasses
212
+ # to define what attributes a LDAP object may have. Ruby/ActiveLdap needs to know
213
+ # what classes are required when creating a new object. Of course, you can leave
214
+ # that field out to default to ['top'] only. Then you can let each application
215
+ # choose what objectClasses their objects should have by calling the method e.g.
216
+ # Group#add_class(*values).
217
+ #
218
+ # Note that is can be very important to define the default :classes value. Due to
219
+ # implementation choices with most LDAP servers, once an object is created, its
220
+ # structural objectclasses may not be removed (or replaced). Setting a sane default
221
+ # may help avoid programmer error later.
222
+ #
223
+ # :classes isn't the only optional argument. If :dn_attribute is left off,
224
+ # it defaults to underscored class name or 'cn'. If :prefix is left off,
225
+ # it will default to 'ou=PLURALIZED_CLASSNAME'. In this
226
+ # case, it would be 'ou=Groups'.
227
+ #
228
+ # :classes should be an Array. :dn_attribute should be a String and so should
229
+ # :prefix.
230
+ #
231
+ #
232
+ # ===== belongs_to
233
+ #
234
+ # This method allows an extension class to make use of other extension classes
235
+ # tying objects together across the LDAP tree. Often, user objects will be
236
+ # members of, or belong_to, Group objects.
237
+ #
238
+ # * dc=dataspill,dc=org
239
+ # |+ ou=People,dc=dataspill,dc=org
240
+ # \
241
+ # |- uid=drewry,ou=People,dc=dataspill,dc=org
242
+ # |- ou=Groups,dc=dataspill,dc=org
243
+ #
244
+ #
245
+ # In the above tree, one such example would be user 'drewry' who is a part of the
246
+ # group 'develop'. You can see this by looking at the 'memberUid' field of 'develop'.
247
+ #
248
+ # irb> develop = Group.find('develop')
249
+ # => ...
250
+ # irb> develop.memberUid
251
+ # => ['drewry', 'builder']
252
+ #
253
+ # If we look at the LDAP entry for 'drewry', we do not see any references to
254
+ # group 'develop'. In order to remedy that, we can use belongs_to
255
+ #
256
+ # irb> class User < ActiveLdap::Base
257
+ # irb* ldap_mapping :dn_attribute => 'uid', :prefix => 'People', :classes => ['top','account']
258
+ # irb* belongs_to :groups, :class => 'Group', :many => 'memberUid', :foreign_key => 'uid'
259
+ # irb* end
260
+ #
261
+ # Now, class User will have a method called 'groups' which will retrieve all
262
+ # Group objects that a user is in.
263
+ #
264
+ # irb> me = User.find('drewry')
265
+ # irb> me.groups
266
+ # => [#<Group:0x000001 ...>, #<Group:0x000002 ...>, ...]
267
+ # irb> me.groups.each { |group| p group.cn };nil
268
+ # "cdrom"
269
+ # "audio"
270
+ # "develop"
271
+ # => nil
272
+ # (Note: nil is just there to make the output cleaner...)
273
+ #
274
+ # TIP: If you weren't sure what the distinguished name attribute was for Group,
275
+ # you could also do the following:
276
+ #
277
+ # irb> me.groups.each { |group| p group.id };nil
278
+ # "cdrom"
279
+ # "audio"
280
+ # "develop"
281
+ # => nil
282
+ #
283
+ # Now let's talk about the arguments. The first argument is the name of the
284
+ # method you wish to create. In this case, we created a method called groups
285
+ # using the symbol :groups. The next collection of arguments are actually a Hash
286
+ # (as with ldap_mapping). :class should be a string that has the name of a
287
+ # class you've already included. If you class is inside of a module, be sure to
288
+ # put the whole name, e.g. :class => "MyLdapModule::Group". :primary_key
289
+ # tells belongs_to what attribute Group objects have that match the
290
+ # :many. :many is the name of the local attribute whose value
291
+ # should be looked up in Group under the primary key. If :foreign_key is left
292
+ # off of the argument list, it is assumed to be the dn_attribute. With this in
293
+ # mind, the above definition could become:
294
+ #
295
+ # irb> class User < ActiveLdap::Base
296
+ # irb* ldap_mapping :dnattr => 'uid', :prefix => 'People', :classes => ['top','account']
297
+ # irb* belongs_to :groups, :class => 'Group', :many => 'memberUid'
298
+ # irb* end
299
+ #
300
+ # In addition, you can do simple membership tests by doing the following:
301
+ #
302
+ # irb> me.groups.member? 'root'
303
+ # => false
304
+ # irb> me.groups.member? 'develop'
305
+ # => true
306
+ #
307
+ # ===== has_many
308
+ #
309
+ # This method is the opposite of belongs_to. Instead of checking other objects in
310
+ # other parts of the LDAP tree to see if you belong to them, you have multiple
311
+ # objects from other trees listed in your object. To show this, we can just
312
+ # invert the example from above:
313
+ #
314
+ # class Group < ActiveLdap::Base
315
+ # ldap_mapping :dn_attribute => 'cn', :prefix => 'ou=Groups', :classes => ['top', 'posixGroup']
316
+ # has_many :members, :class => "User", :wrap => "memberUid", :primary_key => 'uid'
317
+ # end
318
+ #
319
+ # Now we can see that group develop has user 'drewry' as a member, and it can
320
+ # even return all responses in object form just like belongs_to methods.
321
+ #
322
+ # irb> develop = Group.find('develop')
323
+ # => ...
324
+ # irb> develop.members
325
+ # => [#<User:0x000001 ...>, #<User:...>]
326
+ #
327
+ #
328
+ # The arguments for has_many follow the exact same idea that belongs_to's
329
+ # arguments followed. :wrap's contents are used to search for matching
330
+ # :primary_key content. If :primary_key is not specified, it defaults to the
331
+ # dn_attribute of the specified :class.
332
+ #
333
+ # === Using these new classes
334
+ #
335
+ # These new classes have many method calls. Many of them are automatically
336
+ # generated to provide access to the LDAP object's attributes. Other were defined
337
+ # during class creation by special methods like belongs_to. There are a few other
338
+ # methods that do not fall in to these categories.
339
+ #
340
+ #
341
+ # ==== .find
342
+ #
343
+ # .find is a class method that is accessible from any subclass of Base that has
344
+ # 'ldap_mapping' called. When called it returns the first match of the given
345
+ # class.
346
+ #
347
+ # irb> Group.find('*').cn
348
+ # => "root"
349
+ #
350
+ # In this simple example, Group.find took the search string of 'deve*' and
351
+ # searched for the first match in Group where the dnattr matched the query. This
352
+ # is the simplest example of .find.
353
+ #
354
+ # irb> Group.find(:all, '*').collect {|group| group.cn}
355
+ # => ["root", "daemon", "bin", "sys", "adm", "tty", ..., "develop"]
356
+ #
357
+ # Here .find(:all) returns all matches to the same query. Both .find and
358
+ # .find(:all) also can take more expressive arguments:
359
+ #
360
+ # irb> Group.find(:all, :attribute => 'gidNumber', :value => '1003').collect {|group| group.cn}
361
+ # => ["develop"]
362
+ #
363
+ # So it is pretty clear what :attribute and :value do - they are used to query as
364
+ # :attribute=:value.
365
+ #
366
+ # If :attribute is unspecified, it defaults to the dn_attribute.
367
+ #
368
+ # It is also possible to override :attribute and :value by specifying :filter. This
369
+ # argument allows the direct specification of a LDAP filter to retrieve objects by.
370
+ #
371
+ # ==== .search
372
+ # .search is a class method that is accessible from any subclass of Base, and Base.
373
+ # It lets the user perform an arbitrary search against the current LDAP connection
374
+ # irrespetive of LDAP mapping data. This is meant to be useful as a utility method
375
+ # to cover 80% of the cases where a user would want to use Base.connection directly.
376
+ #
377
+ # irb> Base.search(:base => 'dc=example,dc=com', :filter => '(uid=roo*)',
378
+ # :scope => :sub, :attributes => ['uid', 'cn'])
379
+ # => [["uid=root,ou=People,dc=dataspill,dc=org",{"cn"=>["root"], "uidNumber"=>["0"]}]
380
+ # You can specify the :filter, :base, :scope, and :attributes, but they all have defaults --
381
+ # * :filter defaults to objectClass=* - usually this isn't what you want
382
+ # * :base defaults to the base of the class this is executed from (as set in ldap_mapping)
383
+ # * :scope defaults to :sub. Usually you won't need to change it
384
+ # * :attributes defaults to [] and is the list of attributes you want back. Empty means all of them.
385
+ #
386
+ # ==== #valid?
387
+ #
388
+ # valid? is a method that verifies that all attributes that are required by the
389
+ # objects current objectClasses are populated.
390
+ #
391
+ # ==== #save
392
+ #
393
+ # save is a method that writes any changes to an object back to the LDAP server.
394
+ # It automatically handles the addition of new objects, and the modification of
395
+ # existing ones.
396
+ #
397
+ # ==== .exists?
398
+ #
399
+ # exists? is a simple method which returns true is the current object exists in
400
+ # LDAP, or false if it does not.
401
+ #
402
+ # irb> User.exists?("dshadsadsa")
403
+ # => false
404
+ #
405
+ #
406
+ # === ActiveLdap::Base
407
+ #
408
+ # ActiveLdap::Base has come up a number of times in the examples above. Every
409
+ # time, it was being used as the super class for the wrapper objects. While this
410
+ # is it's main purpose, it also handles quite a bit more in the background.
411
+ #
412
+ # ==== What is it?
413
+ #
414
+ # ActiveLdap::Base is the heart of Ruby/ActiveLdap. It does all the schema
415
+ # parsing for validation and attribute-to-method mangling as well as manage the
416
+ # connection to LDAP.
417
+ #
418
+ # ===== establish_connection
419
+ #
420
+ # Base.establish_connection takes many (optional) arguments and is used to
421
+ # connect to the LDAP server. Sometimes you will want to connect anonymously
422
+ # and other times over TLS with user credentials. Base.establish_connection is
423
+ # here to do all of that for you.
424
+ #
425
+ #
426
+ # By default, if you call any subclass of Base, such as Group, it will call
427
+ # Base.establish_connection() if these is no active LDAP connection. If your
428
+ # server allows anonymous binding, and you only want to access data in a
429
+ # read-only fashion, you won't need to call Base.establish_connection. Here
430
+ # is a fully parameterized call:
431
+ #
432
+ # Base.establish_connection(
433
+ # :host => 'ldap.dataspill.org',
434
+ # :port => 389,
435
+ # :base => 'dc=dataspill,dc=org',
436
+ # :logger => logger_object,
437
+ # :bind_dn => "uid=drewry,ou=People,dc=dataspill,dc=org",
438
+ # :password_block => Proc.new { 'password12345' },
439
+ # :allow_anonymous => false,
440
+ # :try_sasl => false
441
+ # )
442
+ #
443
+ # There are quite a few arguments, but luckily many of them have safe defaults:
444
+ # * :host defaults to @@host from configuration.rb waaay back at the setup.rb stage.@
445
+ # * :port defaults to @@port from configuration.rb as well
446
+ # * :base defaults to Base.base() from configuration.rb
447
+ # * :bind_dn defaults @@bind_format from configuration.rb
448
+ # * :logger defaults to a Log4r object that prints fatal messages to stderr
449
+ # * :password_block defaults to nil
450
+ # * :allow_anonymous defaults to true
451
+ # * :try_sasl defaults to false - see Advanced Topics for more on this one.
452
+ #
453
+ #
454
+ # Most of these are obvious, but I'll step through them for completeness:
455
+ # * :host defines the LDAP server hostname to connect to.
456
+ # * :port defines the LDAP server port to connect to.
457
+ # * :method defines the type of connection - :tls, :ssl, :plain
458
+ # * :base specifies the LDAP search base to use with the prefixes defined in all
459
+ # subclasses.
460
+ # * :bind_dn specifies what your server expects when attempting to bind with
461
+ # credentials.
462
+ # * :logger accepts a custom logger object to integrate with any other logging
463
+ # your application uses.
464
+ # * :password_block, if defined, give the Proc block for acquiring the password
465
+ # * :password, if defined, give the user's password as a String
466
+ # * :store_password indicates whether the password should be stored, or if used
467
+ # whether the :password_block should be called on each reconnect.
468
+ # * :allow_anonymous determines whether anonymous binding is allowed if other
469
+ # bind methods fail
470
+ # * :try_sasl, when true, tells ActiveLdap to attempt a SASL-GSSAPI bind
471
+ # * :sasl_quiet, when true, tells the SASL libraries to not spew messages to STDOUT
472
+ # * :method indicates whether to use :ssl, :tls, or :plain
473
+ # * :retries - indicates the number of attempts to reconnect that will be undertaken when a stale connection occurs. -1 means infinite.
474
+ # * :retry_wait - seconds to wait before retrying a connection
475
+ # * :scope - dictates how to find objects. (Default: :one)
476
+ # * :timeout - time in seconds - defaults to disabled. This CAN interrupt search() requests. Be warned.
477
+ # * :retry_on_timeout - whether to reconnect when timeouts occur. Defaults to true
478
+ # See lib/configuration.rb for defaults for each option
479
+ #
480
+ # Base.establish_connection both connects and binds in one step. It follows
481
+ # roughly the following approach:
482
+ #
483
+ # * Connect to host:port using :method
484
+ #
485
+ # * If bind_dn and password_block/password, attempt to bind with credentials.
486
+ # * If that fails or no password_block and anonymous allowed, attempt to bind
487
+ # anonymously.
488
+ # * If that fails, error out.
489
+ #
490
+ # On connect, the configuration options passed in are stored in an internal class variable
491
+ # @configuration which is used to cache the information without ditching the defaults passed in
492
+ # from configuration.rb
493
+ #
494
+ # ===== connection
495
+ #
496
+ # Base.connection returns the ActiveLdap::Connection object.
497
+ #
498
+ # === Exceptions
499
+ #
500
+ # There are a few custom exceptions used in Ruby/ActiveLdap. They are detailed below.
501
+ #
502
+ # ==== DeleteError
503
+ #
504
+ # This exception is raised when #delete fails. It will include LDAP error
505
+ # information that was passed up during the error.
506
+ #
507
+ # ==== SaveError
508
+ #
509
+ # This exception is raised when there is a problem in #save updating or creating
510
+ # an LDAP entry. Often the error messages are cryptic. Looking at the server
511
+ # logs or doing an Ethereal[http://www.ethereal.com] dump of the connection will
512
+ # often provide better insight.
513
+ #
514
+ # ==== AuthenticationError
515
+ #
516
+ # This exception is raised during Base.establish_connection if no valid authentication methods
517
+ # succeeded.
518
+ #
519
+ # ==== ConnectionError
520
+ #
521
+ # This exception is raised during Base.establish_connection if no valid
522
+ # connection to the LDAP server could be created. Check you configuration.rb,
523
+ # Base.establish_connection arguments, and network connectivity! Also check
524
+ # your LDAP server logs to see if it ever saw the request.
525
+ #
526
+ # ==== ObjectClassError
527
+ #
528
+ # This exception is raised when an object class is used that is not defined
529
+ # in the schema.
530
+ #
531
+ # === Others
532
+ #
533
+ # Other exceptions may be raised by the Ruby/LDAP module, or by other subsystems.
534
+ # If you get one of these exceptions and think it should be wrapped, write me an
535
+ # email and let me know where it is and what you expected. For faster results,
536
+ # email a patch!
537
+ #
538
+ # === Putting it all together
539
+ #
540
+ # Now that all of the components of Ruby/ActiveLdap have been covered, it's time
541
+ # to put it all together! The rest of this section will show the steps to setup
542
+ # example user and group management scripts for use with the LDAP tree described
543
+ # above.
544
+ #
545
+ # All of the scripts here are in the package's examples/ directory.
546
+ #
547
+ # ==== Setting up lib/
548
+ #
549
+ # In ldapadmin/lib/ create the file user.rb:
550
+ # cat <<EOF
551
+ # class User < ActiveLdap::Base
552
+ # ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People', :classes => ['top', 'account', 'posixAccount']
553
+ # belongs_to :groups, :class => 'Group', :wrap => 'memberUid'
554
+ # end
555
+ # EOF
556
+ #
557
+ # In ldapadmin/lib/ create the file group.rb:
558
+ # cat <<EOF
559
+ # class Group < ActiveLdap::Base
560
+ # ldap_mapping :classes => ['top', 'posixGroup'], :prefix => 'ou=Group'
561
+ # has_many :members, :class => "User", :many => "memberUid"
562
+ # has_many :primary_members, :class => 'User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
563
+ # end # Group
564
+ # EOF
565
+ #
566
+ # Now, we can write some small scripts to do simple management tasks.
567
+ #
568
+ # ==== Creating LDAP entries
569
+ #
570
+ # Now let's create a really dumb script for adding users - ldapadmin/useradd:
571
+ #
572
+ # #!/usr/bin/ruby -W0
573
+ #
574
+ # require 'active_ldap'
575
+ # require 'lib/user'
576
+ # require 'lib/group'
577
+ # require 'password'
578
+ #
579
+ # argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
580
+ # opts.banner += " USER_NAME CN UID"
581
+ # end
582
+ #
583
+ # if argv.size == 3
584
+ # name, cn, uid = argv
585
+ # else
586
+ # $stderr.puts opts
587
+ # exit 1
588
+ # end
589
+ #
590
+ # pwb = Proc.new do |user|
591
+ # ActiveLdap::Command.read_password("[#{user}] Password: ")
592
+ # end
593
+ #
594
+ # ActiveLdap::Base.establish_connection(:password_block => pwb,
595
+ # :allow_anonymous => false)
596
+ #
597
+ # if User.exists?(name)
598
+ # $stderr.puts("User #{name} already exists.")
599
+ # exit 1
600
+ # end
601
+ #
602
+ # user = User.new(name)
603
+ # user.add_class('shadowAccount')
604
+ # user.cn = cn
605
+ # user.uid_number = uid
606
+ # user.gid_number = uid
607
+ # user.home_directory = "/home/#{name}"
608
+ # user.sn = "somesn"
609
+ # unless user.save
610
+ # puts "failed"
611
+ # puts user.errors.full_messages
612
+ # exit 1
613
+ # end
614
+ #
615
+ # ==== Managing LDAP entries
616
+ #
617
+ # Now let's create another dumb script for modifying users - ldapadmin/usermod:
618
+ #
619
+ # #!/usr/bin/ruby -W0
620
+ #
621
+ # require 'active_ldap'
622
+ # require 'lib/user'
623
+ # require 'lib/group'
624
+ #
625
+ # argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
626
+ # opts.banner += " USER_NAME CN UID"
627
+ # end
628
+ #
629
+ # if argv.size == 3
630
+ # name, cn, uid = argv
631
+ # else
632
+ # $stderr.puts opts
633
+ # exit 1
634
+ # end
635
+ #
636
+ # pwb = Proc.new do |user|
637
+ # ActiveLdap::Command.read_password("[#{user}] Password: ")
638
+ # end
639
+ #
640
+ # ActiveLdap::Base.establish_connection(:password_block => pwb,
641
+ # :allow_anonymous => false)
642
+ #
643
+ # unless User.exists?(name)
644
+ # $stderr.puts("User #{name} doesn't exist.")
645
+ # exit 1
646
+ # end
647
+ #
648
+ # user = User.find(name)
649
+ # user.cn = cn
650
+ # user.uid_number = uid
651
+ # user.gid_number = uid
652
+ # unless user.save
653
+ # puts "failed"
654
+ # puts user.errors.full_messages
655
+ # exit 1
656
+ # end
657
+ #
658
+ # ==== Removing LDAP entries
659
+ #
660
+ # And finally, a dumb script for removing user - ldapadmin/userdel:
661
+ #
662
+ #
663
+ # #!/usr/bin/ruby -W0
664
+ #
665
+ # require 'active_ldap'
666
+ # require 'lib/user'
667
+ # require 'lib/group'
668
+ #
669
+ # argv, opts, options = ActiveLdap::Command.parse_options do |opts, options|
670
+ # opts.banner += " USER_NAME"
671
+ # end
672
+ #
673
+ # if argv.size == 1
674
+ # name = argv.shift
675
+ # else
676
+ # $stderr.puts opts
677
+ # exit 1
678
+ # end
679
+ #
680
+ # pwb = Proc.new do |user|
681
+ # ActiveLdap::Command.read_password("[#{user}] Password: ")
682
+ # end
683
+ #
684
+ # ActiveLdap::Base.establish_connection(:password_block => pwb,
685
+ # :allow_anonymous => false)
686
+ #
687
+ # unless User.exists?(name)
688
+ # $stderr.puts("User #{name} doesn't exist.")
689
+ # exit 1
690
+ # end
691
+ #
692
+ # User.destroy(name)
693
+ #
694
+ # === Advanced Topics
695
+ #
696
+ # Below are some situation tips and tricks to get the most out of Ruby/ActiveLdap.
697
+ #
698
+ #
699
+ # ==== Binary data and other subtypes
700
+ #
701
+ # Sometimes, you may want to store attributes with language specifiers, or
702
+ # perhaps in binary form. This is (finally!) fully supported. To do so,
703
+ # follow the examples below:
704
+ #
705
+ # irb> user = User.new('drewry')
706
+ # => ...
707
+ # # This adds a cn entry in lang-en and whatever the server default is.
708
+ # irb> user.cn = [ 'wad', {'lang-en' => ['wad', 'foo']} ]
709
+ # => ...
710
+ # irb> user.cn
711
+ # => ["wad", {"lang-en-us" => ["wad", "Will Drewry"]}]
712
+ # # Now let's add a binary X.509 certificate (assume objectClass is correct)
713
+ # irb> user.user_certificate = File.read('example.der')
714
+ # => ...
715
+ # irb> user.save
716
+ #
717
+ # So that's a lot to take in. Here's what is going on. I just set the LDAP
718
+ # object's cn to "wad" and cn:lang-en-us to ["wad", "Will Drewry"].
719
+ # Anytime a LDAP subtype is required, you must encapsulate the data in a Hash.
720
+ #
721
+ # But wait a minute, I just read in a binary certificate without wrapping it up.
722
+ # So any binary attribute _that requires ;binary subtyping_ will automagically
723
+ # get wrapped in {'binary' => value} if you don't do it. This keeps your #writes
724
+ # from breaking, and my code from crying. For correctness, I could have easily
725
+ # done the following:
726
+ #
727
+ # irb> user.user_certificate = {'binary' => File.read('example.der')}
728
+ #
729
+ # You should note that some binary data does not use the binary subtype all the time.
730
+ # One example is jpegPhoto. You can use it as jpegPhoto;binary or just as jpegPhoto.
731
+ # Since the schema dictates that it is a binary value, Ruby/ActiveLdap will write
732
+ # it as binary, but the subtype will not be automatically appended as above. The
733
+ # use of the subtype on attributes like jpegPhoto is ultimately decided by the
734
+ # LDAP site policy and not by any programmatic means.
735
+ #
736
+ # The only subtypes defined in LDAPv3 are lang-* and binary. These can be nested
737
+ # though:
738
+ #
739
+ # irb> user.cn = [{'lang-JP-jp' => {'binary' => 'somejp'}}]
740
+ #
741
+ # As I understand it, OpenLDAP does not support nested subtypes, but some
742
+ # documentation I've read suggests that Netscape's LDAP server does. I only
743
+ # have access to OpenLDAP. If anyone tests this out, please let me know how it
744
+ # goes!
745
+ #
746
+ #
747
+ # And that pretty much wraps up this section.
748
+ #
749
+ # ==== Further integration with your environment aka namespacing
750
+ #
751
+ # If you want this to cleanly integrate into your system-wide Ruby include path,
752
+ # you should put your extension classes inside a custom module.
753
+ #
754
+ #
755
+ # Example:
756
+ #
757
+ # ./myldap.rb:
758
+ # require 'active_ldap'
759
+ # require 'myldap/user'
760
+ # require 'myldap/group'
761
+ # module MyLDAP
762
+ # end
763
+ #
764
+ # ./myldap/user.rb:
765
+ # module MyLDAP
766
+ # class User < ActiveLdap::Base
767
+ # ldap_mapping :dn_attribute => 'uid', :prefix => 'ou=People', :classes => ['top', 'account', 'posixAccount']
768
+ # belongs_to :groups, :class => 'MyLDAP::Group', :many => 'memberUid'
769
+ # end
770
+ # end
771
+ #
772
+ # ./myldap/group.rb:
773
+ # module MyLDAP
774
+ # class Group < ActiveLdap::Base
775
+ # ldap_mapping :classes => ['top', 'posixGroup'], :prefix => 'ou=Group'
776
+ # has_many :members, :class => 'MyLDAP::User', :wrap => 'memberUid'
777
+ # has_many :primary_members, :class => 'MyLDAP::User', :foreign_key => 'gidNumber', :primary_key => 'gidNumber'
778
+ # end
779
+ # end
780
+ #
781
+ # Now in your local applications, you can call
782
+ #
783
+ # require 'myldap'
784
+ #
785
+ # MyLDAP::Group.new('foo')
786
+ # ...
787
+ #
788
+ # and everything should work well.
789
+ #
790
+ #
791
+ # ==== force array results for single values
792
+ #
793
+ # Even though Ruby/ActiveLdap attempts to maintain programmatic ease by
794
+ # returning Array values only. By specifying 'true' as an argument to
795
+ # any attribute method you will get back a Array if it is single value.
796
+ # Here's an example:
797
+ #
798
+ # irb> user = User.new('drewry')
799
+ # => ...
800
+ # irb> user.cn(true)
801
+ # => ["Will Drewry"]
802
+ #
803
+ # ==== Dynamic attribute crawling
804
+ #
805
+ # If you use tab completion in irb, you'll notice that you /can/ tab complete the dynamic
806
+ # attribute methods. You can still see which methods are for attributes using
807
+ # Base#attribute_names:
808
+ #
809
+ # irb> d = Group.new('develop')
810
+ # => ...
811
+ # irb> d.attribute_names
812
+ # => ["gidNumber", "cn", "memberUid", "commonName", "description", "userPassword", "objectClass"]
813
+ #
814
+ #
815
+ # ==== Juggling multiple LDAP connections
816
+ #
817
+ # In the same vein as the last tip, you can use multiple LDAP connections by
818
+ # per class as follows:
819
+ #
820
+ # irb> anon_class = Class.new(Base)
821
+ # => ...
822
+ # irb> anon_class.establish_connection
823
+ # => ...
824
+ # irb> auth_class = Class.new(Base)
825
+ # => ...
826
+ # irb> auth_class.establish_connection(:password_block => {'mypass'})
827
+ # => ...
828
+ #
829
+ # This can be useful for doing authentication tests and other such tricks.
830
+ #
831
+ # ==== :try_sasl
832
+ #
833
+ # If you have the Ruby/LDAP package with the SASL/GSSAPI patch from Ian
834
+ # MacDonald's web site, you can use Kerberos to bind to your LDAP server. By
835
+ # default, :try_sasl is false.
836
+ #
837
+ # Also note that you must be using OpenLDAP 2.1.29 or higher to use SASL/GSSAPI
838
+ # due to some bugs in older versions of OpenLDAP.
839
+ #
840
+ # ==== Don't be afraid! [Internals]
841
+ #
842
+ # Don't be afraid to add more methods to the extensions classes and to
843
+ # experiment. That's exactly how I ended up with this package. If you come up
844
+ # with something cool, please share it!
845
+ #
846
+ # The internal structure of ActiveLdap::Base, and thus all its subclasses, is
847
+ # still in flux. I've tried to minimize the changes to the overall API, but
848
+ # the internals are still rough around the edges.
849
+ #
850
+ # ===== Where's ldap_mapping data stored? How can I get to it?
851
+ #
852
+ # When you call ldap_mapping, it overwrites several class methods inherited
853
+ # from Base:
854
+ # * Base.base()
855
+ # * Base.required_classes()
856
+ # * Base.dn_attribute()
857
+ # You can access these from custom class methods by calling MyClass.base(),
858
+ # or whatever. There are predefined instance methods for getting to these
859
+ # from any new instance methods you define:
860
+ # * Base#base()
861
+ # * Base#required_classes()
862
+ # * Base#dn_attribute()
863
+ #
864
+ # ===== What else?
865
+ #
866
+ # Well if you want to use the LDAP connection for anything, I'd suggest still
867
+ # calling Base.connection to get it. There really aren't many other internals
868
+ # that need to be worried about. You could get the LDAP schema with
869
+ # Base.schema.
870
+ #
871
+ # The only other useful tricks are dereferencing and accessing the stored
872
+ # data. Since LDAP attributes can have multiple names, e.g. cn or commonName,
873
+ # any methods you write might need to figure it out. I'd suggest just
874
+ # calling self[attribname] to get the value, but if that's not good enough,
875
+ # you can call look up the stored name by #to_real_attribute_name as follows:
876
+ # irb> to_real_attribute_name('commonName')
877
+ # => 'cn'
878
+ #
879
+ # This tells you the name the attribute is stored in behind the scenes (@data).
880
+ # Again, self[attribname] should be enough for most extensions, but if not,
881
+ # it's probably safe to dabble here.
882
+ #
883
+ # Also, if you like to look up all aliases for an attribute, you can call the
884
+ # following:
885
+ #
886
+ # irb> schema.attribute_aliases('cn')
887
+ # => ['cn','commonName']
888
+ #
889
+ # This is discovered automagically from the LDAP server's schema.
890
+ #
891
+ # == Limitations
892
+ #
893
+ # === Speed
894
+ #
895
+ # Currently, Ruby/ActiveLdap could be faster. I have some recursive type
896
+ # checking going on which slows object creation down, and I'm sure there
897
+ # are many, many other places optimizations can be done. Feel free
898
+ # to send patches, or just hang in there until I can optimize away the
899
+ # slowness.
900
+ #
901
+ # == Feedback
902
+ #
903
+ # Any and all feedback and patches are welcome. I am very excited about this
904
+ # package, and I'd like to see it prove helpful to more people than just myself.
905
+ #
906
+
907
+ require_gem_if_need = Proc.new do |library_name, gem_name|
908
+ begin
909
+ require library_name
910
+ rescue LoadError
911
+ require 'rubygems'
912
+ gem gem_name
913
+ require library_name
914
+ end
915
+ end
916
+
917
+ require_gem_if_need.call("active_support", "activesupport")
918
+
919
+ if Dependencies.respond_to?(:load_paths)
920
+ Dependencies.load_paths << File.expand_path(File.dirname(__FILE__))
921
+ end
922
+
923
+ module ActiveLdap
924
+ VERSION = "0.9.0"
925
+ end
926
+
927
+ if RUBY_PLATFORM.match('linux')
928
+ require 'active_ldap/timeout'
929
+ else
930
+ require 'active_ldap/timeout_stub'
931
+ end
932
+
933
+ require_gem_if_need.call("active_record", "activerecord")
934
+ begin
935
+ require_gem_if_need.call("gettext/active_record", "gettext")
936
+ rescue LoadError
937
+ end
938
+ require 'active_ldap/get_text'
939
+
940
+ require 'active_ldap/base'
941
+
942
+ require 'active_ldap/associations'
943
+ require 'active_ldap/attributes'
944
+ require 'active_ldap/configuration'
945
+ require 'active_ldap/connection'
946
+ require 'active_ldap/operations'
947
+ require 'active_ldap/object_class'
948
+ require 'active_ldap/human_readable'
949
+
950
+ require 'active_ldap/acts/tree'
951
+
952
+ require 'active_ldap/distinguished_name'
953
+ require 'active_ldap/populate'
954
+ require 'active_ldap/escape'
955
+ require 'active_ldap/helper'
956
+
957
+ require 'active_ldap/validations'
958
+ require 'active_ldap/callbacks'
959
+
960
+
961
+ ActiveLdap::Base.class_eval do
962
+ include ActiveLdap::Associations
963
+ include ActiveLdap::Attributes
964
+ include ActiveLdap::Configuration
965
+ include ActiveLdap::Connection
966
+ include ActiveLdap::Operations
967
+ include ActiveLdap::ObjectClass
968
+ include ActiveLdap::HumanReadable
969
+
970
+ include ActiveLdap::Acts::Tree
971
+
972
+ include ActiveLdap::Validations
973
+ include ActiveLdap::Callbacks
974
+ end
975
+
976
+ unless defined?(ACTIVE_LDAP_CONNECTION_ADAPTERS)
977
+ ACTIVE_LDAP_CONNECTION_ADAPTERS = %w(ldap net_ldap)
978
+ end
979
+
980
+ ACTIVE_LDAP_CONNECTION_ADAPTERS.each do |adapter|
981
+ require "active_ldap/adapter/#{adapter}"
982
+ end