activeldap 0.9.0

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