activeldap 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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