activeldap3 1.2.3

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 (443) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGES +691 -0
  3. data/COPYING +340 -0
  4. data/LICENSE +58 -0
  5. data/README +154 -0
  6. data/Rakefile +121 -0
  7. data/TODO +32 -0
  8. data/activeldap3.gemspec +18 -0
  9. data/benchmark/bench-al.rb +263 -0
  10. data/benchmark/config.yaml.sample +5 -0
  11. data/examples/al-admin/README +182 -0
  12. data/examples/al-admin/Rakefile +16 -0
  13. data/examples/al-admin/app/controllers/account_controller.rb +60 -0
  14. data/examples/al-admin/app/controllers/application_controller.rb +46 -0
  15. data/examples/al-admin/app/controllers/attributes_controller.rb +17 -0
  16. data/examples/al-admin/app/controllers/directory_controller.rb +49 -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 +66 -0
  20. data/examples/al-admin/app/controllers/welcome_controller.rb +12 -0
  21. data/examples/al-admin/app/helpers/account_helper.rb +2 -0
  22. data/examples/al-admin/app/helpers/application_helper.rb +46 -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 +17 -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 +58 -0
  32. data/examples/al-admin/app/models/user.rb +91 -0
  33. data/examples/al-admin/app/views/_entry/_attributes_information.html.erb +29 -0
  34. data/examples/al-admin/app/views/_entry/_entry.html.erb +15 -0
  35. data/examples/al-admin/app/views/_schema/_aliases.html.erb +7 -0
  36. data/examples/al-admin/app/views/_switcher/_after.html.erb +2 -0
  37. data/examples/al-admin/app/views/_switcher/_before.html.erb +5 -0
  38. data/examples/al-admin/app/views/account/login.html.erb +26 -0
  39. data/examples/al-admin/app/views/account/sign_up.html.erb +29 -0
  40. data/examples/al-admin/app/views/attributes/_attributes.html.erb +19 -0
  41. data/examples/al-admin/app/views/attributes/_detail.html.erb +29 -0
  42. data/examples/al-admin/app/views/attributes/index.html.erb +3 -0
  43. data/examples/al-admin/app/views/attributes/show.html.erb +31 -0
  44. data/examples/al-admin/app/views/directory/_tree.html.erb +10 -0
  45. data/examples/al-admin/app/views/directory/_tree_view_js.html.erb +25 -0
  46. data/examples/al-admin/app/views/directory/index.html.erb +13 -0
  47. data/examples/al-admin/app/views/directory/populate.html.erb +2 -0
  48. data/examples/al-admin/app/views/layouts/_footer.html.erb +11 -0
  49. data/examples/al-admin/app/views/layouts/_header_menu.html.erb +10 -0
  50. data/examples/al-admin/app/views/layouts/_main_menu.html.erb +18 -0
  51. data/examples/al-admin/app/views/layouts/application.html.erb +57 -0
  52. data/examples/al-admin/app/views/object_classes/_attributes.html.erb +28 -0
  53. data/examples/al-admin/app/views/object_classes/_object_classes.html.erb +19 -0
  54. data/examples/al-admin/app/views/object_classes/index.html.erb +3 -0
  55. data/examples/al-admin/app/views/object_classes/show.html.erb +39 -0
  56. data/examples/al-admin/app/views/syntaxes/_detail.html.erb +14 -0
  57. data/examples/al-admin/app/views/syntaxes/_syntaxes.html.erb +19 -0
  58. data/examples/al-admin/app/views/syntaxes/index.html.erb +3 -0
  59. data/examples/al-admin/app/views/syntaxes/show.html.erb +22 -0
  60. data/examples/al-admin/app/views/users/_attributes_update_form.html.erb +42 -0
  61. data/examples/al-admin/app/views/users/_form.html.erb +13 -0
  62. data/examples/al-admin/app/views/users/_object_classes_update_form.html.erb +46 -0
  63. data/examples/al-admin/app/views/users/_password_change_form.html.erb +20 -0
  64. data/examples/al-admin/app/views/users/edit.html.erb +15 -0
  65. data/examples/al-admin/app/views/users/index.html.erb +10 -0
  66. data/examples/al-admin/app/views/users/show.html.erb +11 -0
  67. data/examples/al-admin/app/views/welcome/index.html.erb +13 -0
  68. data/examples/al-admin/config.ru +7 -0
  69. data/examples/al-admin/config/boot.rb +110 -0
  70. data/examples/al-admin/config/database.yml.example +19 -0
  71. data/examples/al-admin/config/environment.rb +73 -0
  72. data/examples/al-admin/config/environments/development.rb +17 -0
  73. data/examples/al-admin/config/environments/production.rb +24 -0
  74. data/examples/al-admin/config/environments/test.rb +22 -0
  75. data/examples/al-admin/config/initializers/exception_notifier.rb +2 -0
  76. data/examples/al-admin/config/initializers/fast_gettext.rb +3 -0
  77. data/examples/al-admin/config/initializers/inflections.rb +10 -0
  78. data/examples/al-admin/config/initializers/mime_types.rb +5 -0
  79. data/examples/al-admin/config/initializers/session_store.rb +23 -0
  80. data/examples/al-admin/config/ldap.yml.example +21 -0
  81. data/examples/al-admin/config/routes.rb +58 -0
  82. data/examples/al-admin/db/migrate/001_create_users.rb +16 -0
  83. data/examples/al-admin/doc/README_FOR_APP +2 -0
  84. data/examples/al-admin/lib/authenticated_system.rb +124 -0
  85. data/examples/al-admin/lib/authenticated_test_helper.rb +113 -0
  86. data/examples/al-admin/lib/ldap_test_helper.rb +38 -0
  87. data/examples/al-admin/lib/tasks/testing.rake +10 -0
  88. data/examples/al-admin/po/en/al-admin.po +343 -0
  89. data/examples/al-admin/po/ja/al-admin.po +343 -0
  90. data/examples/al-admin/po/nl/al-admin.po +380 -0
  91. data/examples/al-admin/public/.htaccess +40 -0
  92. data/examples/al-admin/public/404.html +30 -0
  93. data/examples/al-admin/public/500.html +30 -0
  94. data/examples/al-admin/public/dispatch.cgi +10 -0
  95. data/examples/al-admin/public/dispatch.fcgi +24 -0
  96. data/examples/al-admin/public/dispatch.rb +10 -0
  97. data/examples/al-admin/public/favicon.ico +0 -0
  98. data/examples/al-admin/public/images/active-ldap.svg +6351 -0
  99. data/examples/al-admin/public/images/al-admin.png +0 -0
  100. data/examples/al-admin/public/images/al-admin.svg +6371 -0
  101. data/examples/al-admin/public/images/header-background.png +0 -0
  102. data/examples/al-admin/public/images/header-background.svg +99 -0
  103. data/examples/al-admin/public/images/rails.png +0 -0
  104. data/examples/al-admin/public/images/spinelz/accordion_tab_left_active.gif +0 -0
  105. data/examples/al-admin/public/images/spinelz/accordion_tab_left_inactive.gif +0 -0
  106. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_active.gif +0 -0
  107. data/examples/al-admin/public/images/spinelz/accordion_tab_middle_inactive.gif +0 -0
  108. data/examples/al-admin/public/images/spinelz/accordion_tab_right_active.gif +0 -0
  109. data/examples/al-admin/public/images/spinelz/accordion_tab_right_inactive.gif +0 -0
  110. data/examples/al-admin/public/images/spinelz/balloon_back.gif +0 -0
  111. data/examples/al-admin/public/images/spinelz/balloon_bottom_left.gif +0 -0
  112. data/examples/al-admin/public/images/spinelz/balloon_bottom_middle.gif +0 -0
  113. data/examples/al-admin/public/images/spinelz/balloon_bottom_right.gif +0 -0
  114. data/examples/al-admin/public/images/spinelz/balloon_left_down_arrow.gif +0 -0
  115. data/examples/al-admin/public/images/spinelz/balloon_left_up_arrow.gif +0 -0
  116. data/examples/al-admin/public/images/spinelz/balloon_middle_left.gif +0 -0
  117. data/examples/al-admin/public/images/spinelz/balloon_middle_right.gif +0 -0
  118. data/examples/al-admin/public/images/spinelz/balloon_right_down_arrow.gif +0 -0
  119. data/examples/al-admin/public/images/spinelz/balloon_right_up_arrow.gif +0 -0
  120. data/examples/al-admin/public/images/spinelz/balloon_top_left.gif +0 -0
  121. data/examples/al-admin/public/images/spinelz/balloon_top_middle.gif +0 -0
  122. data/examples/al-admin/public/images/spinelz/balloon_top_right.gif +0 -0
  123. data/examples/al-admin/public/images/spinelz/barchart_h.gif +0 -0
  124. data/examples/al-admin/public/images/spinelz/barchart_v.gif +0 -0
  125. data/examples/al-admin/public/images/spinelz/button.gif +0 -0
  126. data/examples/al-admin/public/images/spinelz/calendar_default_handler.gif +0 -0
  127. data/examples/al-admin/public/images/spinelz/calendar_delete.gif +0 -0
  128. data/examples/al-admin/public/images/spinelz/calendar_next.gif +0 -0
  129. data/examples/al-admin/public/images/spinelz/calendar_next_second.gif +0 -0
  130. data/examples/al-admin/public/images/spinelz/calendar_pre.gif +0 -0
  131. data/examples/al-admin/public/images/spinelz/calendar_pre_second.gif +0 -0
  132. data/examples/al-admin/public/images/spinelz/calendar_private_icon.gif +0 -0
  133. data/examples/al-admin/public/images/spinelz/calendar_schedule.gif +0 -0
  134. data/examples/al-admin/public/images/spinelz/calender_back.gif +0 -0
  135. data/examples/al-admin/public/images/spinelz/calender_back_second.gif +0 -0
  136. data/examples/al-admin/public/images/spinelz/datepicker2_back.gif +0 -0
  137. data/examples/al-admin/public/images/spinelz/datepicker2_back_second.gif +0 -0
  138. data/examples/al-admin/public/images/spinelz/datepicker2_next.gif +0 -0
  139. data/examples/al-admin/public/images/spinelz/datepicker2_next_second.gif +0 -0
  140. data/examples/al-admin/public/images/spinelz/datepicker2_pre.gif +0 -0
  141. data/examples/al-admin/public/images/spinelz/datepicker2_pre_second.gif +0 -0
  142. data/examples/al-admin/public/images/spinelz/datepicker_back.gif +0 -0
  143. data/examples/al-admin/public/images/spinelz/datepicker_back_second.gif +0 -0
  144. data/examples/al-admin/public/images/spinelz/datepicker_next.gif +0 -0
  145. data/examples/al-admin/public/images/spinelz/datepicker_next_second.gif +0 -0
  146. data/examples/al-admin/public/images/spinelz/datepicker_pre.gif +0 -0
  147. data/examples/al-admin/public/images/spinelz/datepicker_pre_second.gif +0 -0
  148. data/examples/al-admin/public/images/spinelz/grid_down.gif +0 -0
  149. data/examples/al-admin/public/images/spinelz/grid_state.gif +0 -0
  150. data/examples/al-admin/public/images/spinelz/grid_up.gif +0 -0
  151. data/examples/al-admin/public/images/spinelz/icon_day.gif +0 -0
  152. data/examples/al-admin/public/images/spinelz/icon_month.gif +0 -0
  153. data/examples/al-admin/public/images/spinelz/icon_week.gif +0 -0
  154. data/examples/al-admin/public/images/spinelz/menubar_back.gif +0 -0
  155. data/examples/al-admin/public/images/spinelz/menubar_subcontents_back.gif +0 -0
  156. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_active.gif +0 -0
  157. data/examples/al-admin/public/images/spinelz/navPanel_tab_left_inactive.gif +0 -0
  158. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_active.gif +0 -0
  159. data/examples/al-admin/public/images/spinelz/navPanel_tab_middle_inactive.gif +0 -0
  160. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_active.gif +0 -0
  161. data/examples/al-admin/public/images/spinelz/navPanel_tab_right_inactive.gif +0 -0
  162. data/examples/al-admin/public/images/spinelz/select_date.gif +0 -0
  163. data/examples/al-admin/public/images/spinelz/selectabletable_selected.gif +0 -0
  164. data/examples/al-admin/public/images/spinelz/sideBarBox_about.gif +0 -0
  165. data/examples/al-admin/public/images/spinelz/sideBarBox_menu.gif +0 -0
  166. data/examples/al-admin/public/images/spinelz/sideBarBox_sample.gif +0 -0
  167. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomActive.gif +0 -0
  168. data/examples/al-admin/public/images/spinelz/sideBarBox_tabBottomInactive.gif +0 -0
  169. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive.gif +0 -0
  170. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleActive2.gif +0 -0
  171. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive.gif +0 -0
  172. data/examples/al-admin/public/images/spinelz/sideBarBox_tabMiddleInactive2.gif +0 -0
  173. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopActive.gif +0 -0
  174. data/examples/al-admin/public/images/spinelz/sideBarBox_tabTopInactive.gif +0 -0
  175. data/examples/al-admin/public/images/spinelz/sideBarBox_tabbar.gif +0 -0
  176. data/examples/al-admin/public/images/spinelz/sortableTable_down.gif +0 -0
  177. data/examples/al-admin/public/images/spinelz/sortableTable_normal.gif +0 -0
  178. data/examples/al-admin/public/images/spinelz/sortableTable_up.gif +0 -0
  179. data/examples/al-admin/public/images/spinelz/switcher_close.gif +0 -0
  180. data/examples/al-admin/public/images/spinelz/switcher_open.gif +0 -0
  181. data/examples/al-admin/public/images/spinelz/tabBox_close.gif +0 -0
  182. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftActive.gif +0 -0
  183. data/examples/al-admin/public/images/spinelz/tabBox_tabLeftInactive.gif +0 -0
  184. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleActive.gif +0 -0
  185. data/examples/al-admin/public/images/spinelz/tabBox_tabMiddleInactive.gif +0 -0
  186. data/examples/al-admin/public/images/spinelz/tabBox_tabRightActive.gif +0 -0
  187. data/examples/al-admin/public/images/spinelz/tabBox_tabRightInactive.gif +0 -0
  188. data/examples/al-admin/public/images/spinelz/tab_bar.gif +0 -0
  189. data/examples/al-admin/public/images/spinelz/table_back.gif +0 -0
  190. data/examples/al-admin/public/images/spinelz/timepicker_clock.gif +0 -0
  191. data/examples/al-admin/public/images/spinelz/toolbar_close.gif +0 -0
  192. data/examples/al-admin/public/images/spinelz/toolbar_left.gif +0 -0
  193. data/examples/al-admin/public/images/spinelz/toolbar_max.gif +0 -0
  194. data/examples/al-admin/public/images/spinelz/toolbar_middle.gif +0 -0
  195. data/examples/al-admin/public/images/spinelz/toolbar_min.gif +0 -0
  196. data/examples/al-admin/public/images/spinelz/toolbar_next.gif +0 -0
  197. data/examples/al-admin/public/images/spinelz/toolbar_right.gif +0 -0
  198. data/examples/al-admin/public/images/spinelz/treeview_dir.gif +0 -0
  199. data/examples/al-admin/public/images/spinelz/treeview_file.gif +0 -0
  200. data/examples/al-admin/public/images/spinelz/treeview_group.gif +0 -0
  201. data/examples/al-admin/public/images/spinelz/treeview_group_special.gif +0 -0
  202. data/examples/al-admin/public/images/spinelz/treeview_state.gif +0 -0
  203. data/examples/al-admin/public/images/spinelz/treeview_user.gif +0 -0
  204. data/examples/al-admin/public/images/spinelz/window_bottom_left.gif +0 -0
  205. data/examples/al-admin/public/images/spinelz/window_bottom_middle.gif +0 -0
  206. data/examples/al-admin/public/images/spinelz/window_bottom_right.gif +0 -0
  207. data/examples/al-admin/public/images/spinelz/window_close.gif +0 -0
  208. data/examples/al-admin/public/images/spinelz/window_max.gif +0 -0
  209. data/examples/al-admin/public/images/spinelz/window_middle_left.gif +0 -0
  210. data/examples/al-admin/public/images/spinelz/window_middle_right.gif +0 -0
  211. data/examples/al-admin/public/images/spinelz/window_min.gif +0 -0
  212. data/examples/al-admin/public/images/spinelz/window_top_left.gif +0 -0
  213. data/examples/al-admin/public/images/spinelz/window_top_middle.gif +0 -0
  214. data/examples/al-admin/public/images/spinelz/window_top_right.gif +0 -0
  215. data/examples/al-admin/public/javascripts/application.js +2 -0
  216. data/examples/al-admin/public/javascripts/controls.js +963 -0
  217. data/examples/al-admin/public/javascripts/dragdrop.js +973 -0
  218. data/examples/al-admin/public/javascripts/effects.js +1128 -0
  219. data/examples/al-admin/public/javascripts/prototype.js +4320 -0
  220. data/examples/al-admin/public/javascripts/spinelz/accordion.js +185 -0
  221. data/examples/al-admin/public/javascripts/spinelz/ajaxHistory.js +157 -0
  222. data/examples/al-admin/public/javascripts/spinelz/balloon.js +287 -0
  223. data/examples/al-admin/public/javascripts/spinelz/barchart.js +524 -0
  224. data/examples/al-admin/public/javascripts/spinelz/calendar.js +3012 -0
  225. data/examples/al-admin/public/javascripts/spinelz/colorpicker.js +128 -0
  226. data/examples/al-admin/public/javascripts/spinelz/datepicker.js +438 -0
  227. data/examples/al-admin/public/javascripts/spinelz/grid.js +1391 -0
  228. data/examples/al-admin/public/javascripts/spinelz/grid_resizeEx.js +100 -0
  229. data/examples/al-admin/public/javascripts/spinelz/grid_sortabletableEx.js +129 -0
  230. data/examples/al-admin/public/javascripts/spinelz/inplaceEditorEx.js +148 -0
  231. data/examples/al-admin/public/javascripts/spinelz/menubar.js +232 -0
  232. data/examples/al-admin/public/javascripts/spinelz/navPanel.js +170 -0
  233. data/examples/al-admin/public/javascripts/spinelz/selectableTable.js +433 -0
  234. data/examples/al-admin/public/javascripts/spinelz/sideBarBox.js +282 -0
  235. data/examples/al-admin/public/javascripts/spinelz/sideBarBox_effects.js +83 -0
  236. data/examples/al-admin/public/javascripts/spinelz/sortableTable.js +270 -0
  237. data/examples/al-admin/public/javascripts/spinelz/switcher.js +78 -0
  238. data/examples/al-admin/public/javascripts/spinelz/tabBox.js +469 -0
  239. data/examples/al-admin/public/javascripts/spinelz/timepicker.js +384 -0
  240. data/examples/al-admin/public/javascripts/spinelz/toolbar.js +152 -0
  241. data/examples/al-admin/public/javascripts/spinelz/treeview.js +703 -0
  242. data/examples/al-admin/public/javascripts/spinelz/window.js +641 -0
  243. data/examples/al-admin/public/javascripts/spinelz/window_resizeEx.js +130 -0
  244. data/examples/al-admin/public/javascripts/spinelz_lib/builder.js +131 -0
  245. data/examples/al-admin/public/javascripts/spinelz_lib/controls.js +835 -0
  246. data/examples/al-admin/public/javascripts/spinelz_lib/dragdrop.js +944 -0
  247. data/examples/al-admin/public/javascripts/spinelz_lib/effects.js +1090 -0
  248. data/examples/al-admin/public/javascripts/spinelz_lib/json.js +139 -0
  249. data/examples/al-admin/public/javascripts/spinelz_lib/prototype.js +2515 -0
  250. data/examples/al-admin/public/javascripts/spinelz_lib/resize.js +215 -0
  251. data/examples/al-admin/public/javascripts/spinelz_lib/scriptaculous.js +51 -0
  252. data/examples/al-admin/public/javascripts/spinelz_lib/slider.js +278 -0
  253. data/examples/al-admin/public/javascripts/spinelz_lib/spinelz_util.js +1266 -0
  254. data/examples/al-admin/public/javascripts/spinelz_lib/unittest.js +564 -0
  255. data/examples/al-admin/public/robots.txt +1 -0
  256. data/examples/al-admin/public/stylesheets/account.css +41 -0
  257. data/examples/al-admin/public/stylesheets/attributes.css +1 -0
  258. data/examples/al-admin/public/stylesheets/base.css +104 -0
  259. data/examples/al-admin/public/stylesheets/detail.css +36 -0
  260. data/examples/al-admin/public/stylesheets/directory.css +22 -0
  261. data/examples/al-admin/public/stylesheets/object-classes.css +6 -0
  262. data/examples/al-admin/public/stylesheets/rails.css +35 -0
  263. data/examples/al-admin/public/stylesheets/spinelz/accordion.css +59 -0
  264. data/examples/al-admin/public/stylesheets/spinelz/balloon.css +151 -0
  265. data/examples/al-admin/public/stylesheets/spinelz/calendar.css +564 -0
  266. data/examples/al-admin/public/stylesheets/spinelz/datepicker.css +175 -0
  267. data/examples/al-admin/public/stylesheets/spinelz/grid.css +137 -0
  268. data/examples/al-admin/public/stylesheets/spinelz/menubar.css +78 -0
  269. data/examples/al-admin/public/stylesheets/spinelz/modal.css +22 -0
  270. data/examples/al-admin/public/stylesheets/spinelz/navPanel.css +58 -0
  271. data/examples/al-admin/public/stylesheets/spinelz/selectableTable.css +28 -0
  272. data/examples/al-admin/public/stylesheets/spinelz/sideBarBox.css +82 -0
  273. data/examples/al-admin/public/stylesheets/spinelz/sortableTable.css +51 -0
  274. data/examples/al-admin/public/stylesheets/spinelz/switcher.css +23 -0
  275. data/examples/al-admin/public/stylesheets/spinelz/tabBox.css +94 -0
  276. data/examples/al-admin/public/stylesheets/spinelz/timepicker.css +508 -0
  277. data/examples/al-admin/public/stylesheets/spinelz/toolbar.css +82 -0
  278. data/examples/al-admin/public/stylesheets/spinelz/treeview.css +121 -0
  279. data/examples/al-admin/public/stylesheets/spinelz/window.css +140 -0
  280. data/examples/al-admin/public/stylesheets/structure.css +81 -0
  281. data/examples/al-admin/public/stylesheets/syntaxes.css +1 -0
  282. data/examples/al-admin/public/stylesheets/users.css +13 -0
  283. data/examples/al-admin/public/stylesheets/welcome.css +0 -0
  284. data/examples/al-admin/script/about +3 -0
  285. data/examples/al-admin/script/console +3 -0
  286. data/examples/al-admin/script/dbconsole +3 -0
  287. data/examples/al-admin/script/destroy +3 -0
  288. data/examples/al-admin/script/generate +3 -0
  289. data/examples/al-admin/script/performance/benchmarker +3 -0
  290. data/examples/al-admin/script/performance/profiler +3 -0
  291. data/examples/al-admin/script/performance/request +3 -0
  292. data/examples/al-admin/script/plugin +3 -0
  293. data/examples/al-admin/script/process/inspector +3 -0
  294. data/examples/al-admin/script/process/reaper +3 -0
  295. data/examples/al-admin/script/process/spawner +3 -0
  296. data/examples/al-admin/script/runner +3 -0
  297. data/examples/al-admin/script/server +3 -0
  298. data/examples/al-admin/test/fixtures/users.yml +9 -0
  299. data/examples/al-admin/test/functional/account_controller_test.rb +12 -0
  300. data/examples/al-admin/test/functional/attributes_controller_test.rb +8 -0
  301. data/examples/al-admin/test/functional/directory_controller_test.rb +8 -0
  302. data/examples/al-admin/test/functional/object_classes_controller_test.rb +8 -0
  303. data/examples/al-admin/test/functional/syntaxes_controller_test.rb +8 -0
  304. data/examples/al-admin/test/functional/users_controller_test.rb +8 -0
  305. data/examples/al-admin/test/functional/welcome_controller_test.rb +8 -0
  306. data/examples/al-admin/test/integration/sign_up_test.rb +44 -0
  307. data/examples/al-admin/test/run-test.sh +3 -0
  308. data/examples/al-admin/test/test_helper.rb +52 -0
  309. data/examples/al-admin/test/unit/user_test.rb +12 -0
  310. data/examples/al-admin/vendor/plugins/exception_notification/README +111 -0
  311. data/examples/al-admin/vendor/plugins/exception_notification/init.rb +1 -0
  312. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifiable.rb +99 -0
  313. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier.rb +66 -0
  314. data/examples/al-admin/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb +78 -0
  315. data/examples/al-admin/vendor/plugins/exception_notification/test/exception_notifier_helper_test.rb +61 -0
  316. data/examples/al-admin/vendor/plugins/exception_notification/test/test_helper.rb +7 -0
  317. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml +1 -0
  318. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml +7 -0
  319. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml +16 -0
  320. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml +4 -0
  321. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml +2 -0
  322. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml +3 -0
  323. data/examples/al-admin/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml +6 -0
  324. data/examples/config.yaml.example +5 -0
  325. data/examples/example.der +0 -0
  326. data/examples/example.jpg +0 -0
  327. data/examples/groupadd +41 -0
  328. data/examples/groupdel +35 -0
  329. data/examples/groupls +49 -0
  330. data/examples/groupmod +42 -0
  331. data/examples/lpasswd +55 -0
  332. data/examples/objects/group.rb +13 -0
  333. data/examples/objects/ou.rb +4 -0
  334. data/examples/objects/user.rb +20 -0
  335. data/examples/ouadd +38 -0
  336. data/examples/useradd +45 -0
  337. data/examples/useradd-binary +53 -0
  338. data/examples/userdel +34 -0
  339. data/examples/userls +50 -0
  340. data/examples/usermod +42 -0
  341. data/examples/usermod-binary-add +50 -0
  342. data/examples/usermod-binary-add-time +54 -0
  343. data/examples/usermod-binary-del +48 -0
  344. data/examples/usermod-lang-add +43 -0
  345. data/lib/active_ldap.rb +105 -0
  346. data/lib/active_ldap/action_controller/ldap_benchmarking.rb +55 -0
  347. data/lib/active_ldap/acts/tree.rb +75 -0
  348. data/lib/active_ldap/adapter/base.rb +705 -0
  349. data/lib/active_ldap/adapter/jndi.rb +184 -0
  350. data/lib/active_ldap/adapter/jndi_connection.rb +185 -0
  351. data/lib/active_ldap/adapter/ldap.rb +290 -0
  352. data/lib/active_ldap/adapter/ldap_ext.rb +105 -0
  353. data/lib/active_ldap/adapter/net_ldap.rb +309 -0
  354. data/lib/active_ldap/adapter/net_ldap_ext.rb +23 -0
  355. data/lib/active_ldap/association/belongs_to.rb +47 -0
  356. data/lib/active_ldap/association/belongs_to_many.rb +58 -0
  357. data/lib/active_ldap/association/children.rb +21 -0
  358. data/lib/active_ldap/association/collection.rb +105 -0
  359. data/lib/active_ldap/association/has_many.rb +31 -0
  360. data/lib/active_ldap/association/has_many_utils.rb +44 -0
  361. data/lib/active_ldap/association/has_many_wrap.rb +62 -0
  362. data/lib/active_ldap/association/proxy.rb +107 -0
  363. data/lib/active_ldap/associations.rb +202 -0
  364. data/lib/active_ldap/attributes.rb +184 -0
  365. data/lib/active_ldap/base.rb +1594 -0
  366. data/lib/active_ldap/callbacks.rb +52 -0
  367. data/lib/active_ldap/command.rb +49 -0
  368. data/lib/active_ldap/compatible.rb +44 -0
  369. data/lib/active_ldap/configuration.rb +147 -0
  370. data/lib/active_ldap/connection.rb +294 -0
  371. data/lib/active_ldap/distinguished_name.rb +291 -0
  372. data/lib/active_ldap/entry_attribute.rb +78 -0
  373. data/lib/active_ldap/escape.rb +12 -0
  374. data/lib/active_ldap/get_text.rb +9 -0
  375. data/lib/active_ldap/get_text/parser.rb +161 -0
  376. data/lib/active_ldap/get_text_fallback.rb +60 -0
  377. data/lib/active_ldap/get_text_support.rb +20 -0
  378. data/lib/active_ldap/helper.rb +92 -0
  379. data/lib/active_ldap/human_readable.rb +132 -0
  380. data/lib/active_ldap/ldap_error.rb +74 -0
  381. data/lib/active_ldap/ldif.rb +930 -0
  382. data/lib/active_ldap/object_class.rb +95 -0
  383. data/lib/active_ldap/operations.rb +610 -0
  384. data/lib/active_ldap/populate.rb +53 -0
  385. data/lib/active_ldap/railtie.rb +31 -0
  386. data/lib/active_ldap/schema.rb +699 -0
  387. data/lib/active_ldap/schema/syntaxes.rb +417 -0
  388. data/lib/active_ldap/timeout.rb +75 -0
  389. data/lib/active_ldap/timeout_stub.rb +17 -0
  390. data/lib/active_ldap/user_password.rb +92 -0
  391. data/lib/active_ldap/validations.rb +229 -0
  392. data/lib/active_ldap/xml.rb +122 -0
  393. data/po/en/active-ldap.po +4029 -0
  394. data/po/ja/active-ldap.po +4060 -0
  395. data/rails_generators/model_active_ldap/USAGE +17 -0
  396. data/rails_generators/model_active_ldap/model_active_ldap_generator.rb +69 -0
  397. data/rails_generators/model_active_ldap/templates/model_active_ldap.rb +3 -0
  398. data/rails_generators/model_active_ldap/templates/unit_test.rb +8 -0
  399. data/rails_generators/scaffold_active_ldap/scaffold_active_ldap_generator.rb +7 -0
  400. data/rails_generators/scaffold_active_ldap/templates/ldap.yml +18 -0
  401. data/test/al-test-utils.rb +439 -0
  402. data/test/command.rb +112 -0
  403. data/test/config.yaml.sample +6 -0
  404. data/test/fixtures/lower_case_object_class_schema.rb +802 -0
  405. data/test/run-test.rb +44 -0
  406. data/test/test_acts_as_tree.rb +60 -0
  407. data/test/test_adapter.rb +121 -0
  408. data/test/test_associations.rb +664 -0
  409. data/test/test_attributes.rb +117 -0
  410. data/test/test_base.rb +1177 -0
  411. data/test/test_base_per_instance.rb +61 -0
  412. data/test/test_bind.rb +62 -0
  413. data/test/test_callback.rb +37 -0
  414. data/test/test_configuration.rb +40 -0
  415. data/test/test_connection.rb +82 -0
  416. data/test/test_connection_per_class.rb +112 -0
  417. data/test/test_connection_per_dn.rb +112 -0
  418. data/test/test_dn.rb +172 -0
  419. data/test/test_find.rb +176 -0
  420. data/test/test_groupadd.rb +50 -0
  421. data/test/test_groupdel.rb +46 -0
  422. data/test/test_groupls.rb +107 -0
  423. data/test/test_groupmod.rb +51 -0
  424. data/test/test_ldif.rb +1891 -0
  425. data/test/test_load.rb +133 -0
  426. data/test/test_lpasswd.rb +75 -0
  427. data/test/test_object_class.rb +74 -0
  428. data/test/test_reflection.rb +182 -0
  429. data/test/test_schema.rb +559 -0
  430. data/test/test_syntax.rb +383 -0
  431. data/test/test_user.rb +217 -0
  432. data/test/test_user_password.rb +101 -0
  433. data/test/test_useradd-binary.rb +62 -0
  434. data/test/test_useradd.rb +57 -0
  435. data/test/test_userdel.rb +48 -0
  436. data/test/test_userls.rb +91 -0
  437. data/test/test_usermod-binary-add-time.rb +65 -0
  438. data/test/test_usermod-binary-add.rb +64 -0
  439. data/test/test_usermod-binary-del.rb +66 -0
  440. data/test/test_usermod-lang-add.rb +60 -0
  441. data/test/test_usermod.rb +58 -0
  442. data/test/test_validation.rb +274 -0
  443. metadata +502 -0
@@ -0,0 +1,58 @@
1
+ require 'active_ldap/association/collection'
2
+
3
+ module ActiveLdap
4
+ module Association
5
+ class BelongsToMany < Collection
6
+ private
7
+ def insert_entry(entry)
8
+ _foreign_class = foreign_class
9
+ entry = _foreign_class.find(entry) unless entry.is_a?(_foreign_class)
10
+ old_value = entry[@options[:many], true]
11
+ primary_key_name = @options[:primary_key_name]
12
+ if primary_key_name == "dn"
13
+ old_value = dn_values_to_string_values(old_value)
14
+ end
15
+ current_value = @owner[primary_key_name, true]
16
+ current_value = dn_values_to_string_values(current_value)
17
+ new_value = old_value + current_value
18
+ new_value = new_value.uniq.sort
19
+ if old_value != new_value
20
+ entry[@options[:many]] = new_value
21
+ entry.save
22
+ end
23
+ end
24
+
25
+ def delete_entries(entries)
26
+ _foreign_class = foreign_class
27
+ entries.each do |entry|
28
+ entry = _foreign_class.find(entry) unless entry.is_a?(_foreign_class)
29
+ old_value = entry[@options[:many], true]
30
+ primary_key_name = @options[:primary_key_name]
31
+ if primary_key_name == "dn"
32
+ old_value = dn_values_to_string_values(old_value)
33
+ end
34
+ current_value = @owner[primary_key_name, true]
35
+ current_value = dn_values_to_string_values(current_value)
36
+ new_value = old_value - current_value
37
+ new_value = new_value.uniq.sort
38
+ if old_value != new_value
39
+ entry[@options[:many]] = new_value
40
+ entry.save
41
+ end
42
+ end
43
+ end
44
+
45
+ def find_target
46
+ values = @owner[@options[:primary_key_name], true].compact
47
+ return [] if values.empty?
48
+
49
+ key = @options[:many]
50
+ components = values.collect do |value|
51
+ [key, value]
52
+ end
53
+ options = find_options(:filter => [:or, *components])
54
+ foreign_class.find(:all, options)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ require 'active_ldap/association/collection'
2
+
3
+ module ActiveLdap
4
+ module Association
5
+ class Children < Collection
6
+ private
7
+ def insert_entry(entry)
8
+ entry.dn = [entry.id, @owner.dn.to_s].join(",")
9
+ entry.save
10
+ end
11
+
12
+ def find_target
13
+ @owner.find(:all, :base => @owner.dn, :scope => :one)
14
+ end
15
+
16
+ def delete_entries(entries)
17
+ entries.each(&:destroy)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,105 @@
1
+ require 'active_ldap/association/proxy'
2
+
3
+ module ActiveLdap
4
+ module Association
5
+ class Collection < Proxy
6
+ include Enumerable
7
+
8
+ def to_ary
9
+ load_target
10
+ @target.to_ary
11
+ end
12
+
13
+ def reset
14
+ @target = []
15
+ @loaded = false
16
+ end
17
+
18
+ def <<(*entries)
19
+ add_entries(*entries)
20
+ end
21
+ alias_method(:push, :<<)
22
+ alias_method(:concat, :<<)
23
+
24
+ def each(&block)
25
+ to_ary.each(&block)
26
+ end
27
+
28
+ def delete(*entries)
29
+ entries = flatten_deeper(entries).reject do |entry|
30
+ @target.delete(entry) if entry.new_entry?
31
+ entry.new_entry?
32
+ end
33
+ return if entries.empty?
34
+
35
+ delete_entries(entries)
36
+ entries.each do |entry|
37
+ @target.delete(entry)
38
+ end
39
+ end
40
+
41
+ def replace(others)
42
+ load_target
43
+
44
+ entry = @target.first
45
+ if entry.nil?
46
+ deleted_entries = []
47
+ added_entries = others
48
+ else
49
+ base_class = entry.class
50
+ others = others.collect do |other|
51
+ other = base_class.find(other) unless other.is_a?(base_class)
52
+ other
53
+ end
54
+ deleted_entries = @target - others
55
+ added_entries = others - @target
56
+ end
57
+
58
+ delete(deleted_entries)
59
+ concat(added_entries)
60
+ end
61
+
62
+ def exists?
63
+ load_target
64
+ not @target.empty?
65
+ end
66
+
67
+ private
68
+ def flatten_deeper(array)
69
+ array.collect do |element|
70
+ element.respond_to?(:flatten) ? element.flatten : element
71
+ end.flatten
72
+ end
73
+
74
+ def insert_entry(entry)
75
+ entry[@options[:foreign_key_name]] = @owner[@options[:local_key_name]]
76
+ entry.save
77
+ end
78
+
79
+ def add_entries(*entries)
80
+ result = true
81
+ load_target
82
+
83
+ flatten_deeper(entries).each do |entry|
84
+ unless @owner.new_entry?
85
+ infect_connection(entry)
86
+ result &&= insert_entry(entry)
87
+ end
88
+ @target << entry
89
+ end
90
+
91
+ result && self
92
+ end
93
+
94
+ def dn_values_to_string_values(values)
95
+ values.collect do |value|
96
+ if value.is_a?(DN)
97
+ value.to_s
98
+ else
99
+ value
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_ldap/association/collection'
2
+ require 'active_ldap/association/has_many_utils'
3
+
4
+ module ActiveLdap
5
+ module Association
6
+ class HasMany < Collection
7
+ include HasManyUtils
8
+
9
+ private
10
+ def insert_entry(entry)
11
+ entry[foreign_key] = @owner[primary_key]
12
+ entry.save
13
+ end
14
+
15
+ def find_target
16
+ collect_targets(primary_key)
17
+ end
18
+
19
+ def delete_entries(entries)
20
+ _foreign_key = foreign_key
21
+ components = @owner[primary_key, true].reject do |value|
22
+ value.nil?
23
+ end
24
+ filter = [:and,
25
+ [:and, {_foreign_key => components}],
26
+ [:or, {foreign_class.dn_attribute => entries.collect(&:id)}]]
27
+ foreign_class.update_all({_foreign_key => []}, filter)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+ module ActiveLdap
2
+ module Association
3
+ module HasManyUtils
4
+ private
5
+ def collect_targets(requested_target_key, need_requested_targets=false)
6
+ _foreign_key = foreign_key
7
+ return [] if _foreign_key.nil?
8
+
9
+ requested_targets = @owner[requested_target_key, true]
10
+ requested_targets = requested_targets.reject(&:nil?)
11
+ if requested_targets.empty?
12
+ targets = []
13
+ elsif _foreign_key == "dn"
14
+ requested_targets = requested_targets.collect do |target|
15
+ if target.is_a?(DN)
16
+ target
17
+ else
18
+ DN.parse(target)
19
+ end
20
+ end
21
+ targets = []
22
+ requested_targets.each do |target|
23
+ begin
24
+ targets << foreign_class.find(target, find_options)
25
+ rescue EntryNotFound
26
+ end
27
+ end
28
+ else
29
+ components = requested_targets.collect do |value|
30
+ [_foreign_key, value]
31
+ end
32
+ options = find_options(:filter => [:or, *components])
33
+ targets = foreign_class.find(:all, options)
34
+ end
35
+
36
+ if need_requested_targets
37
+ [targets, requested_targets]
38
+ else
39
+ targets
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_ldap/association/collection'
2
+ require 'active_ldap/association/has_many_utils'
3
+
4
+ module ActiveLdap
5
+ module Association
6
+ class HasManyWrap < Collection
7
+ include HasManyUtils
8
+
9
+ private
10
+ def insert_entry(entry)
11
+ old_value = @owner[@options[:wrap], true]
12
+ _foreign_key = foreign_key
13
+ if _foreign_key == "dn"
14
+ old_value = dn_values_to_string_values(old_value)
15
+ end
16
+ current_value = entry[_foreign_key, true]
17
+ current_value = dn_values_to_string_values(current_value)
18
+ new_value = (old_value + current_value).uniq.sort
19
+ if old_value != new_value
20
+ @owner[@options[:wrap]] = new_value
21
+ @owner.save
22
+ end
23
+ end
24
+
25
+ def delete_entries(entries)
26
+ old_value = @owner[@options[:wrap], true]
27
+ _foreign_key = foreign_key
28
+ if _foreign_key == "dn"
29
+ old_value = dn_values_to_string_values(old_value)
30
+ end
31
+ current_value = entries.collect {|entry| entry[_foreign_key]}
32
+ current_value = dn_values_to_string_values(current_value)
33
+ new_value = old_value - current_value
34
+ new_value = new_value.uniq.sort
35
+ if old_value != new_value
36
+ @owner[@options[:wrap]] = new_value
37
+ @owner.save
38
+ end
39
+ end
40
+
41
+ def find_target
42
+ targets, requested_targets = collect_targets(@options[:wrap], true)
43
+ return [] if targets.nil?
44
+
45
+ found_targets = {}
46
+ _foreign_key = foreign_key
47
+ targets.each do |target|
48
+ found_targets[target[_foreign_key]] ||= target
49
+ end
50
+
51
+ klass = foreign_class
52
+ requested_targets.collect do |name|
53
+ found_targets[name] || klass.new(name)
54
+ end
55
+ end
56
+
57
+ def foreign_key
58
+ @options[:primary_key_name] || foreign_class.dn_attribute
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,107 @@
1
+ module ActiveLdap
2
+ module Association
3
+ class Proxy
4
+ alias_method :proxy_respond_to?, :respond_to?
5
+ alias_method :proxy_extend, :extend
6
+ delegate :to_param, :to => :target
7
+
8
+ def initialize(owner, options)
9
+ @owner = owner
10
+ @options = options
11
+ reset
12
+ extend(options[:extend]) if options[:extend]
13
+ end
14
+
15
+ def respond_to?(symbol, include_priv=false)
16
+ proxy_respond_to?(symbol, include_priv) or
17
+ (load_target && @target.respond_to?(symbol, include_priv))
18
+ end
19
+
20
+ def ===(other)
21
+ load_target and other === @target
22
+ end
23
+
24
+ def reset
25
+ @target = nil
26
+ @loaded = false
27
+ end
28
+
29
+ def reload
30
+ reset
31
+ load_target
32
+ end
33
+
34
+ def loaded?
35
+ @loaded
36
+ end
37
+
38
+ def loaded
39
+ @loaded = true
40
+ end
41
+
42
+ def target
43
+ @target
44
+ end
45
+
46
+ def target=(target)
47
+ @target = target
48
+ loaded
49
+ end
50
+
51
+ def exists?
52
+ load_target
53
+ not @target.nil?
54
+ end
55
+
56
+ private
57
+ def method_missing(method, *args, &block)
58
+ load_target
59
+ @target.send(method, *args, &block)
60
+ end
61
+
62
+ def foreign_class
63
+ klass = @owner.class.associated_class(@options[:association_id])
64
+ klass = @owner.class.module_eval(klass) if klass.is_a?(String)
65
+ klass
66
+ end
67
+
68
+ def have_foreign_key?
69
+ false
70
+ end
71
+
72
+ def primary_key
73
+ @options[:primary_key_name] || @owner.dn_attribute
74
+ end
75
+
76
+ def foreign_key
77
+ @options[:foreign_key_name] || foreign_class.dn_attribute
78
+ end
79
+
80
+ def load_target
81
+ if !@owner.new_entry? or have_foreign_key?
82
+ begin
83
+ @target = find_target unless loaded?
84
+ rescue EntryNotFound
85
+ reset
86
+ end
87
+ end
88
+
89
+ loaded if target
90
+ target
91
+ end
92
+
93
+ def find_options(options={})
94
+ if @owner.connection != @owner.class.connection
95
+ {:connection => @owner.connection}.merge(options)
96
+ else
97
+ options
98
+ end
99
+ end
100
+
101
+ def infect_connection(target)
102
+ conn = @owner.instance_variable_get("@connection")
103
+ target.connection = conn if conn
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,202 @@
1
+ require 'active_ldap/association/belongs_to'
2
+ require 'active_ldap/association/belongs_to_many'
3
+ require 'active_ldap/association/has_many'
4
+ require 'active_ldap/association/has_many_wrap'
5
+ require 'active_ldap/association/children'
6
+
7
+ module ActiveLdap
8
+ # Associations
9
+ #
10
+ # Associations provides the class methods needed for
11
+ # the extension classes to create methods using
12
+ # belongs_to and has_many
13
+ module Associations
14
+ def self.append_features(base)
15
+ super
16
+ base.extend(ClassMethods)
17
+ base.class_inheritable_array(:associations)
18
+ base.associations = []
19
+ end
20
+
21
+ module ClassMethods
22
+ def set_associated_class(name, klass)
23
+ @associated_classes ||= {}
24
+ @associated_classes[name.to_s] = klass
25
+ end
26
+
27
+ def associated_class(name)
28
+ @associated_classes[name.to_s]
29
+ end
30
+
31
+ # belongs_to
32
+ #
33
+ # This defines a method for an extension class map its DN key
34
+ # attribute value on to multiple items which reference it by
35
+ # |:foreign_key| in the other LDAP entry covered by class
36
+ # |:class_name|.
37
+ #
38
+ # Example:
39
+ # belongs_to :groups, :class_name => "Group",
40
+ # :many => "memberUid" # Group#memberUid
41
+ # # :primary_key => "uid" # User#uid
42
+ # ## deprecated since 1.1.0. Use :primary_key instead.
43
+ # ## :foreign_key => "uid" # User#uid
44
+ # # dn attribute value is used by default
45
+ # belongs_to :primary_group, :class_name => "Group",
46
+ # :foreign_key => "gidNumber", # User#gidNumber
47
+ # :primary_key => "gidNumber" # Group#gidNumber
48
+ #
49
+ def belongs_to(association_id, options={})
50
+ validate_belongs_to_options(options)
51
+ klass = options[:class]
52
+ klass ||= (options[:class_name] || association_id.to_s).classify
53
+ foreign_key = options[:foreign_key]
54
+ primary_key = options[:primary_key]
55
+ many = options[:many]
56
+ set_associated_class(association_id, klass)
57
+
58
+ opts = {
59
+ :association_id => association_id,
60
+ :foreign_key_name => foreign_key,
61
+ :primary_key_name => primary_key,
62
+ :many => many,
63
+ :extend => options[:extend],
64
+ }
65
+ if opts[:many]
66
+ association_class = Association::BelongsToMany
67
+ foreign_key_name = opts[:foreign_key_name]
68
+ if foreign_key_name
69
+ message = _(":foreign_key belongs_to(:many) option is " \
70
+ "deprecated since 1.1.0. Use :primary_key instead.")
71
+ ActiveSupport::Deprecation.warn(message)
72
+ opts[:primary_key_name] ||= foreign_key_name
73
+ end
74
+ opts[:primary_key_name] ||= dn_attribute
75
+ else
76
+ association_class = Association::BelongsTo
77
+ opts[:foreign_key_name] ||= "#{association_id}_id"
78
+
79
+ before_save(<<-EOC)
80
+ if defined?(@#{association_id})
81
+ association = @#{association_id}
82
+ if association and association.updated?
83
+ self[association.__send__(:primary_key)] =
84
+ association[#{opts[:foreign_key_name].dump}]
85
+ end
86
+ end
87
+ EOC
88
+ end
89
+
90
+ association_accessor(association_id) do |target|
91
+ association_class.new(target, opts)
92
+ end
93
+ end
94
+
95
+
96
+ # has_many
97
+ #
98
+ # This defines a method for an extension class expand an
99
+ # existing multi-element attribute into ActiveLdap objects.
100
+ # This discards any calls which result in entries that
101
+ # don't exist in LDAP!
102
+ #
103
+ # Example:
104
+ # has_many :primary_members, :class_name => "User",
105
+ # :primary_key => "gidNumber", # Group#gidNumber
106
+ # :foreign_key => "gidNumber" # User#gidNumber
107
+ # ## deprecated since 1.1.0. Those options
108
+ # ## are inverted.
109
+ # # :primary_key => "gidNumber", # User#gidNumber
110
+ # # :foreign_key => "gidNumber" # Group#gidNumber
111
+ # has_many :members, :class_name => "User",
112
+ # :wrap => "memberUid" # Group#memberUid
113
+ def has_many(association_id, options = {})
114
+ validate_has_many_options(options)
115
+ klass = options[:class]
116
+ klass ||= (options[:class_name] || association_id.to_s).classify
117
+ foreign_key = options[:foreign_key]
118
+ primary_key = options[:primary_key]
119
+ set_associated_class(association_id, klass)
120
+
121
+ opts = {
122
+ :association_id => association_id,
123
+ :foreign_key_name => foreign_key,
124
+ :primary_key_name => primary_key,
125
+ :wrap => options[:wrap],
126
+ :extend => options[:extend],
127
+ }
128
+ if opts[:wrap]
129
+ association_class = Association::HasManyWrap
130
+ else
131
+ association_class = Association::HasMany
132
+ primary_key_name = opts[:primary_key_name]
133
+ foreign_key_name = opts[:foreign_key_name]
134
+ if primary_key_name != foreign_key_name and
135
+ primary_key_name != "dn" and
136
+ !new.have_attribute?(primary_key_name)
137
+ message = _(":primary_key and :foreign_key has_many options are " \
138
+ "inverted their mean since 1.1.0. Please invert them.")
139
+ ActiveSupport::Deprecation.warn(message)
140
+ opts[:foreign_key_name] = primary_key_name
141
+ opts[:primary_key_name] = foreign_key_name
142
+ end
143
+ end
144
+
145
+ association_accessor(association_id) do |target|
146
+ association_class.new(target, opts)
147
+ end
148
+ end
149
+
150
+ private
151
+ def association_accessor(name, &make_association)
152
+ define_method("__make_#{name}") do
153
+ make_association.call(self)
154
+ end
155
+ associations << name
156
+ association_reader(name, &make_association)
157
+ association_writer(name, &make_association)
158
+ end
159
+
160
+ def association_reader(name, &make_association)
161
+ class_eval(<<-EOM, __FILE__, __LINE__ + 1)
162
+ def #{name}
163
+ @#{name} ||= __make_#{name}
164
+ end
165
+ EOM
166
+ end
167
+
168
+ def association_writer(name, &make_association)
169
+ class_eval(<<-EOM, __FILE__, __LINE__ + 1)
170
+ def #{name}=(new_value)
171
+ association = defined?(@#{name}) ? @#{name} : nil
172
+ association ||= __make_#{name}
173
+ association.replace(new_value)
174
+ @#{name} = new_value.nil? ? nil : association
175
+ @#{name}
176
+ end
177
+ EOM
178
+ end
179
+
180
+ VALID_BELONGS_TO_OPTIONS = [:class, :class_name,
181
+ :foreign_key, :primary_key, :many,
182
+ :extend]
183
+ def validate_belongs_to_options(options)
184
+ options.assert_valid_keys(VALID_BELONGS_TO_OPTIONS)
185
+ end
186
+
187
+ VALID_HAS_MANY_OPTIONS = [:class, :class_name,
188
+ :foreign_key, :primary_key, :wrap,
189
+ :extend]
190
+ def validate_has_many_options(options)
191
+ options.assert_valid_keys(VALID_HAS_MANY_OPTIONS)
192
+ end
193
+ end
194
+
195
+ def clear_association_cache
196
+ return if new_record?
197
+ (self.class.associations || []).each do |association|
198
+ instance_variable_set("@#{association}", nil)
199
+ end
200
+ end
201
+ end
202
+ end