your_platform 0.0.1 → 0.0.2

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 (704) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +39 -11
  3. data/Rakefile +15 -1
  4. data/app/assets/images/file.png +0 -0
  5. data/app/assets/images/img/excel2013_file_128.png +0 -0
  6. data/app/assets/images/img/excel2013_file_bw_107.png +0 -0
  7. data/app/assets/images/img/excel2013_file_bw_semitransparent_107.png +0 -0
  8. data/app/assets/images/img/glyphicons-halflings-white.png +0 -0
  9. data/app/assets/images/img/glyphicons-halflings.png +0 -0
  10. data/app/assets/images/img/gmaps_yellow_marker.png +0 -0
  11. data/app/assets/images/img/gmaps_yellow_marker_38.png +0 -0
  12. data/app/assets/images/markdown_help.png +0 -0
  13. data/app/assets/images/your_platform/breadcrumb-sep.png +0 -0
  14. data/app/assets/javascripts/app-ng.js.coffee +5 -0
  15. data/app/assets/javascripts/attachments.js +2 -0
  16. data/app/assets/javascripts/controllers-ng/bookmark_list_controller.js.coffee +30 -0
  17. data/app/assets/javascripts/controllers-ng/box_controller.js.coffee +37 -0
  18. data/app/assets/javascripts/controllers-ng/profile_angular.js.coffee +151 -0
  19. data/app/assets/javascripts/directives-ng/box_directive.js.coffee +91 -0
  20. data/app/assets/javascripts/directives-ng/star_tool_directive.js.coffee +111 -0
  21. data/app/assets/javascripts/filters-ng/some_filter.js.coffee +0 -0
  22. data/app/assets/javascripts/jquery.appear-1.1.1.js +138 -0
  23. data/app/assets/javascripts/make-js-more-like-ruby.js.coffee +32 -0
  24. data/app/assets/javascripts/mercury.js +456 -0
  25. data/app/assets/javascripts/models-ng/bookmark.js.coffee +28 -0
  26. data/app/assets/javascripts/services-ng/current_user_bookmarks.js.coffee +39 -0
  27. data/app/assets/javascripts/your_platform.js +27 -0
  28. data/app/assets/javascripts/your_platform/address_labels.js.coffee +40 -0
  29. data/app/assets/javascripts/your_platform/attachments.js.coffee +61 -0
  30. data/app/assets/javascripts/your_platform/auto-completion.js.coffee +90 -0
  31. data/app/assets/javascripts/your_platform/best_in_place.js.coffee +8 -0
  32. data/app/assets/javascripts/your_platform/best_in_place_hyperlinks.js.coffee +25 -0
  33. data/app/assets/javascripts/your_platform/best_in_place_tab_key.js.coffee +28 -0
  34. data/app/assets/javascripts/your_platform/boxes.js.coffee +11 -0
  35. data/app/assets/javascripts/your_platform/change_password.js.coffee +22 -0
  36. data/app/assets/javascripts/your_platform/close_dropdowns.js.coffee +18 -0
  37. data/app/assets/javascripts/your_platform/copy_to_clipboard.js.coffee +6 -0
  38. data/app/assets/javascripts/your_platform/datatables.coffee +112 -0
  39. data/app/assets/javascripts/your_platform/datepicker_settings.js.coffee +16 -0
  40. data/app/assets/javascripts/your_platform/edit_tools.js.coffee +19 -0
  41. data/app/assets/javascripts/your_platform/editable_dbl_click.js.coffee +42 -0
  42. data/app/assets/javascripts/your_platform/events.js.coffee +126 -0
  43. data/app/assets/javascripts/your_platform/fix_textarea.js.coffee +11 -0
  44. data/app/assets/javascripts/your_platform/galleria.js.coffee +112 -0
  45. data/app/assets/javascripts/your_platform/groups.js.coffee +36 -0
  46. data/app/assets/javascripts/your_platform/hidden.js.coffee +5 -0
  47. data/app/assets/javascripts/your_platform/links_to_external_sites.js.coffee +12 -0
  48. data/app/assets/javascripts/your_platform/maps.js.coffee +13 -0
  49. data/app/assets/javascripts/your_platform/may_need_review.js.coffee +10 -0
  50. data/app/assets/javascripts/your_platform/navable_title_rename.js.coffee +17 -0
  51. data/app/assets/javascripts/your_platform/officers.js.coffee +35 -0
  52. data/app/assets/javascripts/your_platform/popovers.js.coffee +38 -0
  53. data/app/assets/javascripts/your_platform/posts.js.coffee +58 -0
  54. data/app/assets/javascripts/your_platform/profile_fields.js.coffee +61 -0
  55. data/app/assets/javascripts/your_platform/search.js.coffee +26 -0
  56. data/app/assets/javascripts/your_platform/tooltips.js.coffee +10 -0
  57. data/app/assets/javascripts/your_platform/turbolinks_loading_spinner.js.coffee +83 -0
  58. data/app/assets/javascripts/your_platform/user_avatars.js.coffee +33 -0
  59. data/app/assets/javascripts/your_platform/user_group_memberships.js.coffee +11 -0
  60. data/app/assets/javascripts/your_platform/user_settings.js.coffee +18 -0
  61. data/app/assets/javascripts/your_platform/users_new.js.coffee +54 -0
  62. data/app/assets/stylesheets/bootstrap_layout.css.sass +3 -0
  63. data/app/assets/stylesheets/bootstrap_layout/attachments.css.sass +3 -0
  64. data/app/assets/stylesheets/bootstrap_layout/boxes.css.sass +11 -0
  65. data/app/assets/stylesheets/bootstrap_layout/breadcrumb.css.sass +25 -0
  66. data/app/assets/stylesheets/bootstrap_layout/category_indicator.css.sass +5 -0
  67. data/app/assets/stylesheets/bootstrap_layout/footer.css.sass +14 -0
  68. data/app/assets/stylesheets/bootstrap_layout/galleria.css.sass +8 -0
  69. data/app/assets/stylesheets/bootstrap_layout/header_bar.css.sass +11 -0
  70. data/app/assets/stylesheets/bootstrap_layout/headings.css.sass +10 -0
  71. data/app/assets/stylesheets/bootstrap_layout/logged_in_bar.css.sass +40 -0
  72. data/app/assets/stylesheets/bootstrap_layout/logo.css.sass +2 -0
  73. data/app/assets/stylesheets/bootstrap_layout/modal_fix.css.sass +8 -0
  74. data/app/assets/stylesheets/bootstrap_layout/profiles.css.sass +10 -0
  75. data/app/assets/stylesheets/bootstrap_layout/session_bar.css.sass +60 -0
  76. data/app/assets/stylesheets/bootstrap_layout/stars.css.sass +4 -0
  77. data/app/assets/stylesheets/bootstrap_layout/turbolinks_progress_bar.css.sass +3 -0
  78. data/app/assets/stylesheets/bootstrap_layout/vertical_menu.css.sass +15 -0
  79. data/app/assets/stylesheets/bootstrap_setup.css.sass +4 -0
  80. data/app/assets/stylesheets/your_platform.css.sass +11 -0
  81. data/app/assets/stylesheets/your_platform/address_labels_modal.css.sass +8 -0
  82. data/app/assets/stylesheets/your_platform/attachments.css.sass +75 -0
  83. data/app/assets/stylesheets/your_platform/authorization_info.css.sass +16 -0
  84. data/app/assets/stylesheets/your_platform/auto-completion.css.sass +3 -0
  85. data/app/assets/stylesheets/your_platform/center.css.sass +14 -0
  86. data/app/assets/stylesheets/your_platform/change_password.css.sass +13 -0
  87. data/app/assets/stylesheets/your_platform/corporate_vita.css.sass +2 -0
  88. data/app/assets/stylesheets/your_platform/datatables.css.sass +23 -0
  89. data/app/assets/stylesheets/your_platform/datepicker.css.sass +2 -0
  90. data/app/assets/stylesheets/your_platform/dropdowns.css.sass +8 -0
  91. data/app/assets/stylesheets/your_platform/events.css.sass +68 -0
  92. data/app/assets/stylesheets/your_platform/forms.css.sass +25 -0
  93. data/app/assets/stylesheets/your_platform/galleria.css.sass +12 -0
  94. data/app/assets/stylesheets/your_platform/groups.css.sass +8 -0
  95. data/app/assets/stylesheets/your_platform/groups_table.css.sass +8 -0
  96. data/app/assets/stylesheets/your_platform/hidden.css.sass +3 -0
  97. data/app/assets/stylesheets/your_platform/images.css.sass +50 -0
  98. data/app/assets/stylesheets/your_platform/last_activities.css.sass +17 -0
  99. data/app/assets/stylesheets/your_platform/latest_members.css.sass +7 -0
  100. data/app/assets/stylesheets/your_platform/login.css.sass +4 -0
  101. data/app/assets/stylesheets/your_platform/maps.css.sass +22 -0
  102. data/app/assets/stylesheets/your_platform/markdown_help.css.sass +5 -0
  103. data/app/assets/stylesheets/your_platform/may_need_review.css.sass +3 -0
  104. data/app/assets/stylesheets/your_platform/pages.css.sass +12 -0
  105. data/app/assets/stylesheets/your_platform/password_strength.css.sass +73 -0
  106. data/app/assets/stylesheets/your_platform/picture_attachments.css.sass +7 -0
  107. data/app/assets/stylesheets/your_platform/popovers.css.sass +13 -0
  108. data/app/assets/stylesheets/your_platform/posts.css.sass +32 -0
  109. data/app/assets/stylesheets/your_platform/profiles.css.sass +153 -0
  110. data/app/assets/stylesheets/your_platform/search_preview.css.sass +4 -0
  111. data/app/assets/stylesheets/your_platform/star_tool.css.sass +2 -0
  112. data/app/assets/stylesheets/your_platform/tooltips.css.sass +7 -0
  113. data/app/assets/stylesheets/your_platform/turbolinks_loading_spinner.css.sass +3 -0
  114. data/app/assets/stylesheets/your_platform/user_avatars.css.sass +8 -0
  115. data/app/assets/stylesheets/your_platform/user_group_memberships.css.sass +4 -0
  116. data/app/assets/stylesheets/your_platform/vertical_nav.css.sass +7 -0
  117. data/app/controllers/activities_controller.rb +6 -0
  118. data/app/controllers/application_controller.rb +236 -0
  119. data/app/controllers/attachments_controller.rb +97 -0
  120. data/app/controllers/blog_posts_controller.rb +50 -0
  121. data/app/controllers/bookmarks_controller.rb +33 -0
  122. data/app/controllers/corporations_controller.rb +22 -0
  123. data/app/controllers/errors_controller.rb +27 -0
  124. data/app/controllers/events_controller.rb +262 -0
  125. data/app/controllers/groups_controller.rb +257 -0
  126. data/app/controllers/officers_controller.rb +28 -0
  127. data/app/controllers/pages_controller.rb +67 -0
  128. data/app/controllers/posts_controller.rb +81 -0
  129. data/app/controllers/profile_fields_controller.rb +132 -0
  130. data/app/controllers/root_controller.rb +35 -0
  131. data/app/controllers/search_controller.rb +149 -0
  132. data/app/controllers/sessions_controller.rb +21 -0
  133. data/app/controllers/setup_controller.rb +80 -0
  134. data/app/controllers/statistics_controller.rb +38 -0
  135. data/app/controllers/status_group_memberships_controller.rb +28 -0
  136. data/app/controllers/terms_of_use_controller.rb +35 -0
  137. data/app/controllers/user_accounts_controller.rb +55 -0
  138. data/app/controllers/user_group_memberships_controller.rb +75 -0
  139. data/app/controllers/user_settings_controller.rb +57 -0
  140. data/app/controllers/users_controller.rb +125 -0
  141. data/app/controllers/workflows_controller.rb +19 -0
  142. data/app/helpers/application_helper.rb +25 -0
  143. data/app/helpers/attachments_helper.rb +2 -0
  144. data/app/helpers/auto_completion_helper.rb +33 -0
  145. data/app/helpers/avatar_helper.rb +70 -0
  146. data/app/helpers/bookmarks_helper.rb +22 -0
  147. data/app/helpers/box_helper.rb +56 -0
  148. data/app/helpers/breadcrumbs_helper.rb +62 -0
  149. data/app/helpers/corporate_vita_helper.rb +34 -0
  150. data/app/helpers/events_helper.rb +28 -0
  151. data/app/helpers/flash_helper.rb +60 -0
  152. data/app/helpers/footer_helper.rb +13 -0
  153. data/app/helpers/galleria_helper.rb +13 -0
  154. data/app/helpers/groups_helper.rb +66 -0
  155. data/app/helpers/horizontal_nav_helper.rb +11 -0
  156. data/app/helpers/i18n_helper.rb +10 -0
  157. data/app/helpers/icon_helper.rb +35 -0
  158. data/app/helpers/mailer_helper.rb +7 -0
  159. data/app/helpers/map_helper.rb +26 -0
  160. data/app/helpers/markdown_helper.rb +22 -0
  161. data/app/helpers/markup_helper.rb +25 -0
  162. data/app/helpers/officers_helper.rb +13 -0
  163. data/app/helpers/password_helper.rb +23 -0
  164. data/app/helpers/profile_field_helper.rb +40 -0
  165. data/app/helpers/profile_helper.rb +69 -0
  166. data/app/helpers/quick_link_helper.rb +53 -0
  167. data/app/helpers/special_pages_helper.rb +9 -0
  168. data/app/helpers/structureable_helper.rb +11 -0
  169. data/app/helpers/sublime_helper.rb +16 -0
  170. data/app/helpers/title_helper.rb +52 -0
  171. data/app/helpers/tool_buttons_helper.rb +74 -0
  172. data/app/helpers/unicode_helper.rb +9 -0
  173. data/app/helpers/users_helper.rb +13 -0
  174. data/app/helpers/vertical_nav_helper.rb +84 -0
  175. data/app/helpers/workflows_helper.rb +37 -0
  176. data/app/mailers/event_mailer.rb +13 -0
  177. data/app/mailers/post_mailer.rb +11 -0
  178. data/app/mailers/user_account_mailer.rb +17 -0
  179. data/app/models/ability.rb +321 -0
  180. data/app/models/active_record_associations_patches.rb +26 -0
  181. data/app/models/active_record_cache_extension.rb +152 -0
  182. data/app/models/active_record_find_by_extension.rb +20 -0
  183. data/app/models/active_record_json_url_extension.rb +51 -0
  184. data/app/models/active_record_metric_events_extension.rb +22 -0
  185. data/app/models/active_record_read_only_extension.rb +35 -0
  186. data/app/models/active_record_update_attributes_bip_extension.rb +24 -0
  187. data/app/models/address_label.rb +50 -0
  188. data/app/models/app_version.rb +49 -0
  189. data/app/models/array.rb +15 -0
  190. data/app/models/attachment.rb +76 -0
  191. data/app/models/bashpass_password.rb +32 -0
  192. data/app/models/blog_post.rb +2 -0
  193. data/app/models/bookmark.rb +67 -0
  194. data/app/models/cache_additions.rb +15 -0
  195. data/app/models/cache_store_extension.rb +78 -0
  196. data/app/models/concerns/user_avatar.rb +16 -0
  197. data/app/models/concerns/user_corporations.rb +44 -0
  198. data/app/models/concerns/user_date_of_birth.rb +74 -0
  199. data/app/models/concerns/user_profile.rb +102 -0
  200. data/app/models/corporation.rb +80 -0
  201. data/app/models/dag_link.rb +29 -0
  202. data/app/models/event.rb +235 -0
  203. data/app/models/flag.rb +18 -0
  204. data/app/models/flagable.rb +62 -0
  205. data/app/models/geo_location.rb +92 -0
  206. data/app/models/group.rb +224 -0
  207. data/app/models/group_mixins/corporations.rb +141 -0
  208. data/app/models/group_mixins/developers.rb +41 -0
  209. data/app/models/group_mixins/everyone.rb +72 -0
  210. data/app/models/group_mixins/guests.rb +61 -0
  211. data/app/models/group_mixins/hidden_users.rb +43 -0
  212. data/app/models/group_mixins/import.rb +321 -0
  213. data/app/models/group_mixins/memberships.rb +207 -0
  214. data/app/models/group_mixins/officers.rb +47 -0
  215. data/app/models/group_mixins/roles.rb +41 -0
  216. data/app/models/horizontal_nav.rb +32 -0
  217. data/app/models/last_seen_activity.rb +10 -0
  218. data/app/models/list_export.rb +359 -0
  219. data/app/models/may_need_review.rb +54 -0
  220. data/app/models/metric_logger.rb +83 -0
  221. data/app/models/nav_node.rb +169 -0
  222. data/app/models/navable.rb +46 -0
  223. data/app/models/object_to_b_extension.rb +12 -0
  224. data/app/models/page.rb +212 -0
  225. data/app/models/password.rb +28 -0
  226. data/app/models/post.rb +199 -0
  227. data/app/models/profile.rb +36 -0
  228. data/app/models/profile_field.rb +196 -0
  229. data/app/models/profile_field_mixins/has_child_profile_fields.rb +114 -0
  230. data/app/models/profile_field_types/about.rb +9 -0
  231. data/app/models/profile_field_types/academic_degree.rb +10 -0
  232. data/app/models/profile_field_types/address.rb +88 -0
  233. data/app/models/profile_field_types/bank_account.rb +12 -0
  234. data/app/models/profile_field_types/competence.rb +7 -0
  235. data/app/models/profile_field_types/custom.rb +12 -0
  236. data/app/models/profile_field_types/date.rb +14 -0
  237. data/app/models/profile_field_types/description.rb +15 -0
  238. data/app/models/profile_field_types/email.rb +20 -0
  239. data/app/models/profile_field_types/employment.rb +24 -0
  240. data/app/models/profile_field_types/general.rb +9 -0
  241. data/app/models/profile_field_types/homepage.rb +19 -0
  242. data/app/models/profile_field_types/name_surrounding.rb +11 -0
  243. data/app/models/profile_field_types/organization.rb +24 -0
  244. data/app/models/profile_field_types/phone.rb +37 -0
  245. data/app/models/profile_field_types/professional_category.rb +8 -0
  246. data/app/models/profile_field_types/study.rb +18 -0
  247. data/app/models/profile_section.rb +49 -0
  248. data/app/models/profileable.rb +58 -0
  249. data/app/models/profileable_mixins/address.rb +118 -0
  250. data/app/models/relationship.rb +78 -0
  251. data/app/models/role.rb +164 -0
  252. data/app/models/setting.rb +9 -0
  253. data/app/models/status_group.rb +28 -0
  254. data/app/models/status_group_membership.rb +189 -0
  255. data/app/models/status_group_membership_info.rb +54 -0
  256. data/app/models/structureable.rb +164 -0
  257. data/app/models/structureable_mixins/has_special_groups.rb +127 -0
  258. data/app/models/structureable_mixins/roles.rb +275 -0
  259. data/app/models/user.rb +878 -0
  260. data/app/models/user_account.rb +162 -0
  261. data/app/models/user_alias.rb +112 -0
  262. data/app/models/user_group_membership.rb +300 -0
  263. data/app/models/user_group_membership_mixins/validity_range.rb +206 -0
  264. data/app/models/user_group_membership_mixins/validity_range_for_indirect_memberships.rb +160 -0
  265. data/app/models/user_mixins/identification.rb +36 -0
  266. data/app/models/user_mixins/memberships.rb +75 -0
  267. data/app/models/workflow.rb +40 -0
  268. data/app/models/workflow_kit/add_to_group_brick.rb +21 -0
  269. data/app/models/workflow_kit/destroy_account_and_end_memberships_if_needed_brick.rb +19 -0
  270. data/app/models/workflow_kit/last_membership_needs_review_brick.rb +19 -0
  271. data/app/models/workflow_kit/mark_as_deceased_brick.rb +17 -0
  272. data/app/models/workflow_kit/remove_from_group_brick.rb +27 -0
  273. data/app/models/workflow_kit/test_brick.rb +13 -0
  274. data/app/pdfs/address_labels_pdf.rb +157 -0
  275. data/app/presenters/base_presenter.rb +52 -0
  276. data/app/presenters/horizontal_nav_presenter.rb +106 -0
  277. data/app/uploaders/attachment_uploader.rb +148 -0
  278. data/app/views/activities/index.html.haml +25 -0
  279. data/app/views/attachments/_attachment.html.haml +20 -0
  280. data/app/views/attachments/_description.html.haml +11 -0
  281. data/app/views/attachments/_documents.html.haml +17 -0
  282. data/app/views/attachments/_drop_field.html.haml +46 -0
  283. data/app/views/attachments/_picture.html.haml +2 -0
  284. data/app/views/attachments/_pictures.html.haml +10 -0
  285. data/app/views/attachments/_video.html.haml +8 -0
  286. data/app/views/attachments/create.js.erb +1 -0
  287. data/app/views/attachments/destroy.js.erb +1 -0
  288. data/app/views/blog_posts/create.js.erb +17 -0
  289. data/app/views/bookmarks/_list.html.haml +7 -0
  290. data/app/views/bookmarks/update.js.erb +4 -0
  291. data/app/views/devise/mailer/reset_password_instructions.html.haml +8 -0
  292. data/app/views/devise/passwords/edit.html.haml +1 -0
  293. data/app/views/devise/passwords/new.html.haml +12 -0
  294. data/app/views/devise/registrations/edit.html.haml +1 -0
  295. data/app/views/devise/sessions/new.html.haml +14 -0
  296. data/app/views/devise/shared/_links.haml +26 -0
  297. data/app/views/errors/show.html.haml +5 -0
  298. data/app/views/errors/unauthorized.html.haml +7 -0
  299. data/app/views/event_mailer/invitation_email.html.erb +63 -0
  300. data/app/views/events/_event_details.html.haml +54 -0
  301. data/app/views/events/_events_lis.html.haml +29 -0
  302. data/app/views/events/_invitation_text.html.erb +8 -0
  303. data/app/views/events/_pictures.html.haml +5 -0
  304. data/app/views/events/_public_index.html.haml +16 -0
  305. data/app/views/events/index.html.haml +24 -0
  306. data/app/views/events/show.html.haml +50 -0
  307. data/app/views/groups/_address_labels_modal.html.haml +27 -0
  308. data/app/views/groups/_export_button.html.haml +66 -0
  309. data/app/views/groups/_group_list.html.haml +25 -0
  310. data/app/views/groups/_member_avatars.html.haml +4 -0
  311. data/app/views/groups/_member_list.html.haml +15 -0
  312. data/app/views/groups/index.html.erb +11 -0
  313. data/app/views/groups/index_mine.html.haml +7 -0
  314. data/app/views/groups/show.html.haml +79 -0
  315. data/app/views/last_seen_activities/_index.html.haml +19 -0
  316. data/app/views/layouts/_add_structureable_additions.html.haml +15 -0
  317. data/app/views/layouts/_box.html.haml +16 -0
  318. data/app/views/layouts/_help_button.html.haml +1 -0
  319. data/app/views/layouts/_role_preview_switcher.html.haml +20 -0
  320. data/app/views/layouts/_session_bar_avatar.html.haml +1 -0
  321. data/app/views/layouts/_vertical_nav.html.haml +5 -0
  322. data/app/views/layouts/bootstrap.html.haml +146 -0
  323. data/app/views/layouts/mercury.html.erb +23 -0
  324. data/app/views/officers/_history_notice.html.haml +4 -0
  325. data/app/views/officers/_officers_box.html.haml +33 -0
  326. data/app/views/officers/_officers_group_entry.html.haml +45 -0
  327. data/app/views/pages/_attachments.html.haml +21 -0
  328. data/app/views/pages/_page.html.haml +28 -0
  329. data/app/views/pages/_pictures.html.haml +2 -0
  330. data/app/views/pages/_videos.html.erb +8 -0
  331. data/app/views/pages/show.html.haml +39 -0
  332. data/app/views/post_mailer/post_email.html.erb +17 -0
  333. data/app/views/posts/_new_post_template_text.html.haml +6 -0
  334. data/app/views/posts/_post.html.haml +13 -0
  335. data/app/views/posts/_post_quote.html.haml +18 -0
  336. data/app/views/posts/_posts.html.haml +6 -0
  337. data/app/views/posts/index.html.haml +9 -0
  338. data/app/views/posts/new.html.haml +42 -0
  339. data/app/views/posts/show.html.haml +8 -0
  340. data/app/views/profile_fields/_postal_address_flag_switch.html.haml +21 -0
  341. data/app/views/profile_fields/_profile_field.html.haml +41 -0
  342. data/app/views/profile_fields/create.js.erb +26 -0
  343. data/app/views/profile_fields/destroy.js.erb +3 -0
  344. data/app/views/profiles/_add_profile_field_button.html.haml +15 -0
  345. data/app/views/profiles/_profile_section_ul.html.haml +8 -0
  346. data/app/views/profiles/_section.html.haml +28 -0
  347. data/app/views/profiles/_send_group_message_button.html.haml +4 -0
  348. data/app/views/root/_latest_members_box.html.haml +19 -0
  349. data/app/views/root/_start_page_elements.html.haml +0 -0
  350. data/app/views/root/_what_is_new.html.haml +21 -0
  351. data/app/views/search/_preview_blog_post.html.haml +1 -0
  352. data/app/views/search/_preview_corporation.html.haml +5 -0
  353. data/app/views/search/_preview_group.html.haml +4 -0
  354. data/app/views/search/_preview_page.html.haml +11 -0
  355. data/app/views/search/_preview_user.html.haml +14 -0
  356. data/app/views/search/index.html.haml +42 -0
  357. data/app/views/setup/index.html.haml +56 -0
  358. data/app/views/shared/_add_structureable.html.haml +22 -0
  359. data/app/views/shared/_authorization_info.html.haml +22 -0
  360. data/app/views/shared/_flags.html.haml +5 -0
  361. data/app/views/shared/_markdown_help.html.haml +4 -0
  362. data/app/views/shared/_search_box.html.haml +2 -0
  363. data/app/views/shared/_upcoming_events.html.haml +33 -0
  364. data/app/views/statistics/index.html.haml +16 -0
  365. data/app/views/statistics/show.html.haml +13 -0
  366. data/app/views/terms_of_use/_checkbox.html.haml +1 -0
  367. data/app/views/terms_of_use/_terms.html.haml +1 -0
  368. data/app/views/terms_of_use/index.html.haml +19 -0
  369. data/app/views/user_account_mailer/welcome_email.html.erb +32 -0
  370. data/app/views/user_accounts/_change_password.html.haml +149 -0
  371. data/app/views/user_accounts/_user_account.html.haml +39 -0
  372. data/app/views/user_group_memberships/_list_item.html.haml +9 -0
  373. data/app/views/user_group_memberships/_memberships_table.html.haml +56 -0
  374. data/app/views/user_group_memberships/_new.html.haml +18 -0
  375. data/app/views/user_group_memberships/create.js.erb +9 -0
  376. data/app/views/user_group_memberships/index.html.haml +5 -0
  377. data/app/views/user_settings/show.html.haml +36 -0
  378. data/app/views/users/_avatar.html.haml +16 -0
  379. data/app/views/users/_communication_box.html.haml +8 -0
  380. data/app/views/users/_corporate_vita.html.haml +23 -0
  381. data/app/views/users/_dead_badge.html.haml +3 -0
  382. data/app/views/users/_deceased_modal.html.haml +24 -0
  383. data/app/views/users/_hidden_badge.html.haml +4 -0
  384. data/app/views/users/_hidden_flag_switch.html.haml +20 -0
  385. data/app/views/users/_special_general_info_fields.html.haml +10 -0
  386. data/app/views/users/_user_corporation_attribute.html.haml +6 -0
  387. data/app/views/users/_user_name_attribute.html.haml +4 -0
  388. data/app/views/users/_user_title.html.haml +5 -0
  389. data/app/views/users/_workflow_triggers.html.haml +23 -0
  390. data/app/views/users/new.html.haml +55 -0
  391. data/app/views/users/show.html.haml +79 -0
  392. data/config/environment.rb +5 -0
  393. data/config/initializers/active_record_cache_extension.rb +1 -0
  394. data/config/initializers/active_record_find_by_extension.rb +1 -0
  395. data/config/initializers/active_record_flagable_extension.rb +2 -0
  396. data/config/initializers/active_record_json_url_extension.rb +1 -0
  397. data/config/initializers/active_record_may_need_review_extension.rb +2 -0
  398. data/config/initializers/active_record_metric_events_extension.rb +1 -0
  399. data/config/initializers/active_record_navable_extension.rb +6 -0
  400. data/config/initializers/active_record_profileable_extension.rb +4 -0
  401. data/config/initializers/active_record_read_only_extension.rb +1 -0
  402. data/config/initializers/active_record_structureable_extension.rb +3 -0
  403. data/config/initializers/active_record_update_attributes_bip_extension.rb +1 -0
  404. data/config/initializers/array_extension.rb +1 -0
  405. data/config/initializers/best_in_place_display_definitions.rb +31 -0
  406. data/config/initializers/cache_store_extension.rb +1 -0
  407. data/config/initializers/devise.rb +240 -0
  408. data/config/initializers/fnordmetric.rb +14 -0
  409. data/config/initializers/formtastic.rb +76 -0
  410. data/config/initializers/group_type_column_patches.rb +11 -0
  411. data/config/initializers/mime_types.rb +1 -0
  412. data/config/initializers/mini_profiler.rb +32 -0
  413. data/config/initializers/object_to_b_extension.rb +1 -0
  414. data/config/initializers/refile.rb +22 -0
  415. data/config/initializers/sidekiq.rb +12 -0
  416. data/config/locales/attachments/de.yml +33 -0
  417. data/config/locales/bookmarks/de.yml +3 -0
  418. data/config/locales/bookmarks/en.yml +3 -0
  419. data/config/locales/common_expressions/de.yml +5 -0
  420. data/config/locales/common_expressions/en.yml +5 -0
  421. data/config/locales/companies/de.yml +4 -0
  422. data/config/locales/companies/en.yml +4 -0
  423. data/config/locales/de.yml +30 -0
  424. data/config/locales/devise/de.yml +60 -0
  425. data/config/locales/devise/en.yml +62 -0
  426. data/config/locales/en.yml +25 -0
  427. data/config/locales/events/de.yml +34 -0
  428. data/config/locales/events/en.yml +34 -0
  429. data/config/locales/forms/de.yml +3 -0
  430. data/config/locales/groups/de.yml +56 -0
  431. data/config/locales/groups/en.yml +47 -0
  432. data/config/locales/officers/de.yml +10 -0
  433. data/config/locales/pages/de.yml +15 -0
  434. data/config/locales/pages/en.yml +14 -0
  435. data/config/locales/pagination/de.yml +6 -0
  436. data/config/locales/pagination/en.yml +5 -0
  437. data/config/locales/password_strength/de.yml +9 -0
  438. data/config/locales/password_strength/en.yml +9 -0
  439. data/config/locales/posts/de.yml +9 -0
  440. data/config/locales/profile_fields/de.yml +78 -0
  441. data/config/locales/profile_fields/en.yml +22 -0
  442. data/config/locales/profiles/de.yml +47 -0
  443. data/config/locales/profiles/en.yml +44 -0
  444. data/config/locales/roles/de.yml +9 -0
  445. data/config/locales/root/de.yml +3 -0
  446. data/config/locales/root/en.yml +3 -0
  447. data/config/locales/search/de.yml +11 -0
  448. data/config/locales/search/en.yml +11 -0
  449. data/config/locales/sessions/de.yml +37 -0
  450. data/config/locales/sessions/en.yml +37 -0
  451. data/config/locales/setup/de.yml +26 -0
  452. data/config/locales/setup/en.yml +26 -0
  453. data/config/locales/statistics/de.yml +6 -0
  454. data/config/locales/terms_of_use/de.yml +6 -0
  455. data/config/locales/tools/de.yml +9 -0
  456. data/config/locales/tools/en.yml +9 -0
  457. data/config/locales/user_accounts/de.yml +16 -0
  458. data/config/locales/user_accounts/en.yml +13 -0
  459. data/config/locales/user_settings/de.yml +9 -0
  460. data/config/locales/users/de.yml +82 -0
  461. data/config/locales/users/en.yml +51 -0
  462. data/config/locales/workflows/de.yml +4 -0
  463. data/config/locales/workflows/en.yml +4 -0
  464. data/config/routes.rb +104 -0
  465. data/db/migrate/20120403002734_create_users.rb +12 -0
  466. data/db/migrate/20120403011601_create_profile_fields.rb +11 -0
  467. data/db/migrate/20120403161549_remove_user_email_column.rb +5 -0
  468. data/db/migrate/20120405222050_encrypt_password.rb +8 -0
  469. data/db/migrate/20120425161138_create_dag_links.rb +14 -0
  470. data/db/migrate/20120425162644_create_pages.rb +10 -0
  471. data/db/migrate/20120426023322_create_groups.rb +9 -0
  472. data/db/migrate/20120426090436_create_nav_nodes.rb +18 -0
  473. data/db/migrate/20120427021934_create_user_accounts.rb +12 -0
  474. data/db/migrate/20120427044338_add_foreign_key_to_user_accounts.rb +7 -0
  475. data/db/migrate/20120427150156_add_group_token.rb +8 -0
  476. data/db/migrate/20120507165551_make_profile_fields_polymorphic.rb +11 -0
  477. data/db/migrate/20120508130729_add_profile_field_acts_as_tree.rb +9 -0
  478. data/db/migrate/20120508152233_change_profile_field_value_to_text.rb +9 -0
  479. data/db/migrate/20120508201550_add_group_internal_token.rb +11 -0
  480. data/db/migrate/20120511090234_create_workflows.rb +9 -0
  481. data/db/migrate/20120701115059_add_password_digest_to_user_accounts.rb +5 -0
  482. data/db/migrate/20120710193308_remove_salt_from_user_accounts.rb +5 -0
  483. data/db/migrate/20120713102445_add_deleted_at_to_dag_links.rb +5 -0
  484. data/db/migrate/20120722005022_create_workflow_kit_workflows.workflow_kit.rb +11 -0
  485. data/db/migrate/20120722005023_create_workflow_kit_steps.workflow_kit.rb +12 -0
  486. data/db/migrate/20120722005024_create_workflow_kit_parameters.workflow_kit.rb +12 -0
  487. data/db/migrate/20120723165226_add_female_to_users.rb +5 -0
  488. data/db/migrate/20120811140509_create_flags.rb +11 -0
  489. data/db/migrate/20120814100529_create_attachments.rb +13 -0
  490. data/db/migrate/20120815205610_add_content_type_and_file_size_to_attachments.rb +6 -0
  491. data/db/migrate/20130118220014_add_relationships_table_without_dag.rb +10 -0
  492. data/db/migrate/20130207214331_create_events.rb +12 -0
  493. data/db/migrate/20130208215253_create_status_group_membership_infos.rb +11 -0
  494. data/db/migrate/20130220184943_create_stars.rb +11 -0
  495. data/db/migrate/20130309193623_add_devise_to_user_accounts.rb +72 -0
  496. data/db/migrate/20130310003840_rename_stars_to_bookmarks.rb +9 -0
  497. data/db/migrate/20130310004622_fix_column_names_for_bookmarks.rb +6 -0
  498. data/db/migrate/20130313211414_create_geo_infos.rb +13 -0
  499. data/db/migrate/20130313234131_create_geo_locations.rb +16 -0
  500. data/db/migrate/20130314011638_drop_geo_infos.rb +5 -0
  501. data/db/migrate/20130315072759_add_invalid_to_geo_location.rb +5 -0
  502. data/db/migrate/20130315073149_exchange_invalid_for_queried_at_in_geo_location.rb +8 -0
  503. data/db/migrate/20130320003051_add_redirect_to_to_page.rb +5 -0
  504. data/db/migrate/20130329231657_create_posts.rb +15 -0
  505. data/db/migrate/20130404223735_add_entire_message_to_posts.rb +5 -0
  506. data/db/migrate/20130409192959_add_author_to_page.rb +5 -0
  507. data/db/migrate/20130908011215_add_type_to_pages.rb +5 -0
  508. data/db/migrate/20131115114715_validity_range_for_dag_links.rb +16 -0
  509. data/db/migrate/20140611170430_create_activities.rb +23 -0
  510. data/db/migrate/20140808223512_create_last_seen_activities.rb +12 -0
  511. data/db/migrate/20141008101744_add_location_to_events.rb +5 -0
  512. data/db/migrate/20141010130344_add_publish_on_website_to_events.rb +6 -0
  513. data/db/migrate/20141010134227_add_auth_token_to_user_accounts.rb +5 -0
  514. data/db/migrate/20141018143323_add_accepted_terms_to_users.rb +6 -0
  515. data/db/migrate/20141018221659_add_author_to_attachments.rb +5 -0
  516. data/db/migrate/20141102223954_add_body_to_groups.rb +5 -0
  517. data/db/migrate/20141110193830_create_settings.rb +17 -0
  518. data/db/migrate/20141202140522_add_indices.rb +6 -0
  519. data/db/migrate/20141209161946_add_keys.rb +20 -0
  520. data/db/migrate/20150127013809_add_incognito_to_users.rb +5 -0
  521. data/db/migrate/20150129194501_add_indices_for_polymorphic_references.rb +13 -0
  522. data/db/migrate/20150304192448_add_type_to_groups.rb +5 -0
  523. data/db/migrate/20150313221004_add_avatar_id_to_users.rb +5 -0
  524. data/lib/best_in_place/controller_extensions.rb +25 -0
  525. data/lib/best_in_place/helper.rb +127 -0
  526. data/lib/tasks/db_bootstrap.rake +37 -0
  527. data/lib/tasks/your_platform_tasks.rake +4 -0
  528. data/lib/templates/erb/scaffold/_form.html.erb +11 -0
  529. data/lib/your_platform.rb +6 -2
  530. data/lib/your_platform/engine.rb +127 -0
  531. data/lib/your_platform/version.rb +1 -1
  532. data/spec/factories/attachment.rb +12 -0
  533. data/spec/factories/blog_post.rb +10 -0
  534. data/spec/factories/company.rb +7 -0
  535. data/spec/factories/corporation.rb +20 -0
  536. data/spec/factories/event.rb +13 -0
  537. data/spec/factories/group.rb +36 -0
  538. data/spec/factories/html_email.eml +1059 -0
  539. data/spec/factories/mail_message.rb +30 -0
  540. data/spec/factories/page.rb +10 -0
  541. data/spec/factories/relationship.rb +13 -0
  542. data/spec/factories/status_group_membership.rb +21 -0
  543. data/spec/factories/user.rb +97 -0
  544. data/spec/factories/workflow.rb +44 -0
  545. data/spec/features/blog_post_spec.rb +46 -0
  546. data/spec/features/corporate_vita_events_spec.rb +114 -0
  547. data/spec/features/corporate_vita_spec.rb +258 -0
  548. data/spec/features/edit_mode_after_clicking_a_link_spec.rb +20 -0
  549. data/spec/features/events_spec.rb +356 -0
  550. data/spec/features/group_export_spec.rb +19 -0
  551. data/spec/features/group_post_spec.rb +89 -0
  552. data/spec/features/groups_of_groups_page_spec.rb +67 -0
  553. data/spec/features/groups_page_spec.rb +66 -0
  554. data/spec/features/groups_table_spec.rb +32 -0
  555. data/spec/features/help_page_spec.rb +22 -0
  556. data/spec/features/intranet_root_page_spec.rb +18 -0
  557. data/spec/features/locales_spec.rb +36 -0
  558. data/spec/features/maps_spec.rb +53 -0
  559. data/spec/features/mini_profiler_spec.rb +37 -0
  560. data/spec/features/officers_spec.rb +61 -0
  561. data/spec/features/page_redirects_spec.rb +23 -0
  562. data/spec/features/page_spec.rb +20 -0
  563. data/spec/features/postal_address_flag_spec.rb +46 -0
  564. data/spec/features/relationships_on_user_page_spec.rb +78 -0
  565. data/spec/features/review_membership_spec.rb +44 -0
  566. data/spec/features/search_field_spec.rb +121 -0
  567. data/spec/features/setup_spec.rb +63 -0
  568. data/spec/features/user_change_date_of_birth_spec.rb +26 -0
  569. data/spec/features/vertical_nav_spec.rb +27 -0
  570. data/spec/features/what_is_new_box_spec.rb +33 -0
  571. data/spec/helpers/attachments_helper_spec.rb +15 -0
  572. data/spec/models/ability_spec.rb +93 -0
  573. data/spec/models/active_record_cache_extension_spec.rb +177 -0
  574. data/spec/models/active_record_find_by_extension_spec.rb +26 -0
  575. data/spec/models/active_record_json_url_extension_spec.rb +79 -0
  576. data/spec/models/address_label_spec.rb +144 -0
  577. data/spec/models/app_version_spec.rb +38 -0
  578. data/spec/models/attachment_spec.rb +5 -0
  579. data/spec/models/bookmark_spec.rb +70 -0
  580. data/spec/models/concerns/user_corporations_spec.rb +71 -0
  581. data/spec/models/corporation_spec.rb +128 -0
  582. data/spec/models/dag_link_spec.rb +48 -0
  583. data/spec/models/event_spec.rb +267 -0
  584. data/spec/models/flag_spec.rb +20 -0
  585. data/spec/models/flagable_spec.rb +55 -0
  586. data/spec/models/geo_location_spec.rb +126 -0
  587. data/spec/models/group_mixins/corporations_spec.rb +95 -0
  588. data/spec/models/group_mixins/everyone_spec.rb +64 -0
  589. data/spec/models/group_mixins/guests_spec.rb +75 -0
  590. data/spec/models/group_mixins/hidden_users_spec.rb +21 -0
  591. data/spec/models/group_mixins/import_spec.rb +93 -0
  592. data/spec/models/group_mixins/memberships_spec.rb +303 -0
  593. data/spec/models/group_mixins/officers_spec.rb +63 -0
  594. data/spec/models/group_mixins/roles_spec.rb +46 -0
  595. data/spec/models/group_spec.rb +341 -0
  596. data/spec/models/list_export_spec.rb +155 -0
  597. data/spec/models/may_need_review_spec.rb +114 -0
  598. data/spec/models/nav_node_spec.rb +277 -0
  599. data/spec/models/navable_spec.rb +54 -0
  600. data/spec/models/page_spec.rb +185 -0
  601. data/spec/models/post_spec.rb +271 -0
  602. data/spec/models/profile_field_mixins/has_child_profile_fields_spec.rb +73 -0
  603. data/spec/models/profile_field_spec.rb +482 -0
  604. data/spec/models/profile_section_spec.rb +89 -0
  605. data/spec/models/profile_spec.rb +74 -0
  606. data/spec/models/profileable_mixins/adress_spec.rb +93 -0
  607. data/spec/models/profileable_spec.rb +152 -0
  608. data/spec/models/relationship_spec.rb +113 -0
  609. data/spec/models/status_group_membership_spec.rb +350 -0
  610. data/spec/models/status_group_spec.rb +103 -0
  611. data/spec/models/structureable_mixins/has_special_groups_spec.rb +479 -0
  612. data/spec/models/structureable_mixins/roles_spec.rb +517 -0
  613. data/spec/models/structureable_spec.rb +128 -0
  614. data/spec/models/user_account_spec.rb +142 -0
  615. data/spec/models/user_alias_spec.rb +57 -0
  616. data/spec/models/user_group_membership_mixins/validity_range_for_indirect_memberships_spec.rb +291 -0
  617. data/spec/models/user_group_membership_mixins/validity_range_spec.rb +293 -0
  618. data/spec/models/user_group_membership_spec.rb +428 -0
  619. data/spec/models/user_mixins/identification_spec.rb +27 -0
  620. data/spec/models/user_mixins/memberships_spec.rb +138 -0
  621. data/spec/models/user_spec.rb +1794 -0
  622. data/spec/old_yp_spec_helper.rb +46 -0
  623. data/spec/spec_helper.rb +350 -0
  624. data/spec/support/auto_complete.rb +22 -0
  625. data/spec/support/capybara/flash_helpers.rb +37 -0
  626. data/spec/support/capybara/profile_steps.rb +73 -0
  627. data/spec/support/capybara/session_steps.rb +53 -0
  628. data/spec/support/capybara/user_account_helpers.rb +15 -0
  629. data/spec/support/debug.rb +8 -0
  630. data/spec/support/devise-controller_macros.rb +15 -0
  631. data/spec/support/geocoder/stubs.rb +60 -0
  632. data/spec/support/press_enter.rb +15 -0
  633. data/spec/support/time_travel.rb +9 -0
  634. data/spec/support/uploads/image-upload.png +0 -0
  635. data/spec/support/uploads/pdf-upload.pdf +0 -0
  636. data/spec/support/wait_for_ajax.rb +39 -0
  637. data/spec/support/wait_for_cache.rb +7 -0
  638. data/spec/uploaders/attachment_uploader_spec.rb +47 -0
  639. data/vendor/assets/images/flags.png +0 -0
  640. data/vendor/assets/images/galleria/classic-loader.gif +0 -0
  641. data/vendor/assets/images/galleria/classic-map.png +0 -0
  642. data/vendor/assets/javascripts/best_in_place_datetime.js.coffee +45 -0
  643. data/vendor/assets/javascripts/galleria-classic.js +100 -0
  644. data/vendor/assets/javascripts/galleria.js +6919 -0
  645. data/vendor/assets/javascripts/gmaps4rails.js +2 -0
  646. data/vendor/assets/javascripts/gmaps4rails/all.js +1 -0
  647. data/vendor/assets/javascripts/gmaps4rails/base.coffee +1 -0
  648. data/vendor/assets/javascripts/gmaps4rails/base/common.coffee +43 -0
  649. data/vendor/assets/javascripts/gmaps4rails/base/configuration.coffee +7 -0
  650. data/vendor/assets/javascripts/gmaps4rails/base/gmaps.coffee +13 -0
  651. data/vendor/assets/javascripts/gmaps4rails/base/interfaces/basic_interface.coffee +15 -0
  652. data/vendor/assets/javascripts/gmaps4rails/base/interfaces/controller_interface.coffee +15 -0
  653. data/vendor/assets/javascripts/gmaps4rails/base/interfaces/map_interface.coffee +27 -0
  654. data/vendor/assets/javascripts/gmaps4rails/base/interfaces/marker_interface.coffee +15 -0
  655. data/vendor/assets/javascripts/gmaps4rails/base/main.coffee +124 -0
  656. data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/circle_controller.coffee +29 -0
  657. data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/kml_controller.coffee +5 -0
  658. data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/marker_controller.coffee +76 -0
  659. data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/polygon_controller.coffee +29 -0
  660. data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/polyline_controller.coffee +29 -0
  661. data/vendor/assets/javascripts/gmaps4rails/base/objects/circle.coffee +12 -0
  662. data/vendor/assets/javascripts/gmaps4rails/base/objects/kml.coffee +8 -0
  663. data/vendor/assets/javascripts/gmaps4rails/base/objects/map.coffee +62 -0
  664. data/vendor/assets/javascripts/gmaps4rails/base/objects/marker.coffee +24 -0
  665. data/vendor/assets/javascripts/gmaps4rails/base/objects/polygon.coffee +11 -0
  666. data/vendor/assets/javascripts/gmaps4rails/base/objects/polyline.coffee +11 -0
  667. data/vendor/assets/javascripts/gmaps4rails/bing.coffee +1 -0
  668. data/vendor/assets/javascripts/gmaps4rails/bing/main.coffee +29 -0
  669. data/vendor/assets/javascripts/gmaps4rails/bing/objects/map.coffee +63 -0
  670. data/vendor/assets/javascripts/gmaps4rails/bing/objects/marker.coffee +78 -0
  671. data/vendor/assets/javascripts/gmaps4rails/bing/shared.coffee +20 -0
  672. data/vendor/assets/javascripts/gmaps4rails/google.coffee +1 -0
  673. data/vendor/assets/javascripts/gmaps4rails/google/main.coffee +47 -0
  674. data/vendor/assets/javascripts/gmaps4rails/google/objects/circle.coffee +38 -0
  675. data/vendor/assets/javascripts/gmaps4rails/google/objects/kml.coffee +16 -0
  676. data/vendor/assets/javascripts/gmaps4rails/google/objects/map.coffee +71 -0
  677. data/vendor/assets/javascripts/gmaps4rails/google/objects/marker.coffee +114 -0
  678. data/vendor/assets/javascripts/gmaps4rails/google/objects/polygon.coffee +38 -0
  679. data/vendor/assets/javascripts/gmaps4rails/google/objects/polyline.coffee +49 -0
  680. data/vendor/assets/javascripts/gmaps4rails/google/shared.coffee +27 -0
  681. data/vendor/assets/javascripts/gmaps4rails/openlayers.coffee +1 -0
  682. data/vendor/assets/javascripts/gmaps4rails/openlayers/main.coffee +138 -0
  683. data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/map.coffee +49 -0
  684. data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/marker.coffee +68 -0
  685. data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/polyline.coffee +39 -0
  686. data/vendor/assets/javascripts/gmaps4rails/openlayers/shared.coffee +19 -0
  687. data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +2223 -0
  688. data/vendor/assets/javascripts/jquery-ui-timepicker-de.js +26 -0
  689. data/vendor/assets/javascripts/jquery.ui.datepicker-de.js +23 -0
  690. data/vendor/assets/javascripts/password_strength.js +149 -0
  691. data/vendor/assets/javascripts/zxcvbn.js +43 -0
  692. data/vendor/assets/stylesheets/flags.css.scss +259 -0
  693. data/vendor/assets/stylesheets/galleria-classic.css.scss +239 -0
  694. data/vendor/assets/stylesheets/gmaps4rails.css +24 -0
  695. data/vendor/assets/stylesheets/mercury.css +24 -0
  696. data/vendor/scripts/bashpass/README.md +29 -0
  697. data/vendor/scripts/bashpass/bashpass +124 -0
  698. data/vendor/scripts/bashpass/bashpass-APACHE-LICENSE +201 -0
  699. data/vendor/scripts/bashpass/german.dic +40794 -0
  700. metadata +1540 -16
  701. data/.gitignore +0 -17
  702. data/Gemfile +0 -4
  703. data/LICENSE.txt +0 -4
  704. data/your_platform.gemspec +0 -19
@@ -0,0 +1,275 @@
1
+ #
2
+ # This module extends the Structureable models by methods for the interaction with roles.
3
+ # For example, a structureable object is being equipped with a `admins` association
4
+ # that lists all (direct) admin users of the object. To make a user an admin of a structureable
5
+ # object, you may call `object.admins << user`.
6
+ #
7
+ # This module is included by `include StructureableMixins::Roles`.
8
+ #
9
+ # The helper methods used in the module are defined in `StructureableMixins::HasSpecialGroups`.
10
+ #
11
+ module StructureableMixins::Roles
12
+
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ end
17
+
18
+ def fill_cache
19
+ super
20
+ if respond_to?(:child_groups) # TODO: Refactor this. It should be possible to find the admins for a user.
21
+ find_admins
22
+ admins_of_ancestors
23
+ admins_of_self_and_ancestors
24
+ officers_of_self_and_parent_groups
25
+ officers_groups_of_self_and_descendant_groups
26
+ officers_of_self_and_ancestors
27
+ officers_of_self_and_ancestor_groups
28
+ end
29
+ end
30
+
31
+ def delete_cache
32
+ super
33
+ delete_caches_concerning_roles
34
+ end
35
+
36
+ def delete_caches_concerning_roles
37
+ if is_a? Group
38
+ # For an admins_parent, this is called recursively until the original group
39
+ # is reached.
40
+ #
41
+ # group
42
+ # |---- officers_parent
43
+ # |------------ admins_parent
44
+ # |------------ some officer group
45
+ #
46
+ if has_flag?(:officers_parent) || has_flag?(:admins_parent)
47
+ parent_groups.each do |group|
48
+ group.delete_cache
49
+ if group.descendants.count > 0
50
+ bulk_delete_cached :admins_of_ancestors, group.descendants
51
+ bulk_delete_cached :admins_of_self_and_ancestors, group.descendants
52
+ bulk_delete_cached "*officers*", group.descendants
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+
60
+ # Officers
61
+ # ==========================================================================================
62
+ #
63
+ # Each structureable object may have officers, e.g. the president of the organization.
64
+ # Officers are collected in a subgroup with the flag :officers_parent. This
65
+ # officers_parent group may also have subgroups. But, of course, the officers_parent
66
+ # group must not have another officers_parent subgroup.
67
+ #
68
+ # Calling `some_structureable_object.officers` lists all officer users of the structureable
69
+ # itself **and of the sub groups** of the structureable object.
70
+ #
71
+
72
+ def find_officers_parent_group
73
+ find_special_group(:officers_parent)
74
+ end
75
+
76
+ def create_officers_parent_group
77
+ if self.ancestor_groups(true).find_all_by_flag(:officers_parent).count == 0 and not self.has_flag?(:officers_parent)
78
+ # Do not allow officer cascades.
79
+ create_special_group(:officers_parent)
80
+ end
81
+ end
82
+
83
+ def find_or_create_officers_parent_group
84
+ find_officers_parent_group || create_officers_parent_group
85
+ end
86
+
87
+ def officers_parent
88
+ find_or_create_officers_parent_group
89
+ end
90
+
91
+ def officers_parent!
92
+ find_officers_parent_group || raise('special group :officers_parent does not exist.')
93
+ end
94
+
95
+ # This method returns all officer_parent groups of the structureable object itself
96
+ # and of the descendant groups of the structureable object.
97
+ #
98
+ def find_officers_parent_groups_of_self_and_of_descendant_groups
99
+ [self.find_officers_parent_group] + self.descendant_groups.find_all_by_flag(:officers_parent) - [nil]
100
+ end
101
+
102
+ # This method lists all officer groups of the group, i.e. all subgroups of the
103
+ # officers_parent group.
104
+ #
105
+ def find_officers_groups
106
+ self.find_officers_parent_group.try(:descendant_groups) || []
107
+ end
108
+ def officers_groups
109
+ self.officers_parent.descendant_groups
110
+ end
111
+
112
+ def direct_officers
113
+ self.find_officers_parent_group.try(:descendant_users) || []
114
+ end
115
+
116
+ def officers_of_self_and_parent_groups
117
+ cached do
118
+ direct_officers + (parent_groups.collect { |parent_group| parent_group.direct_officers }.flatten)
119
+ end
120
+ end
121
+
122
+ def officers_groups_of_self_and_descendant_groups
123
+ cached do
124
+ self.find_officers_parent_groups_of_self_and_of_descendant_groups.collect do |officers_parent|
125
+ officers_parent.descendant_groups
126
+ end.flatten.uniq
127
+ end
128
+ end
129
+
130
+ def find_officers
131
+ cached do
132
+ if respond_to? :child_groups
133
+ find_officers_parent_group.try(:descendant_users)
134
+ end || []
135
+ end
136
+ end
137
+
138
+ def officers_of_ancestors
139
+ cached { ancestors.collect { |ancestor| ancestor.find_officers }.flatten }
140
+ end
141
+
142
+ def officers_of_ancestor_groups
143
+ cached { ancestor_groups.collect { |ancestor| ancestor.find_officers }.flatten }
144
+ end
145
+
146
+ def officers_of_self_and_ancestors
147
+ cached { find_officers + officers_of_ancestors }
148
+ end
149
+
150
+ def officers_of_self_and_ancestor_groups
151
+ cached { find_officers + officers_of_ancestor_groups }
152
+ end
153
+
154
+ # This method returns all officer users, as well all of this group as of its subgroups.
155
+ #
156
+ def officers
157
+ self.find_officers_parent_groups_of_self_and_of_descendant_groups.collect do |officers_parent|
158
+ officers_parent.descendant_users
159
+ end.flatten.uniq
160
+ end
161
+
162
+
163
+ # Admins
164
+ # ==========================================================================================
165
+ #
166
+ # Each structureable object may have admins (users), which are collected in the
167
+ # `admins_parent` special group of the structureable object, which is a subgroup
168
+ # of the officers_parent subgroup of the structureable object.
169
+ #
170
+ # my_structureable
171
+ # |----------- officers_parent
172
+ # |----------- admins_parent
173
+ #
174
+ # One can access or assign the admins of the structureable object by calling:
175
+ #
176
+ # my_structureable.admins # => Array of users
177
+ # my_structureable.admins << user
178
+ #
179
+
180
+ def find_admins_parent_group
181
+ find_special_group(:admins_parent, parent_element: find_officers_parent_group )
182
+ end
183
+
184
+ def create_admins_parent_group
185
+ delete_cached(:find_admins)
186
+ create_special_group(:admins_parent, parent_element: find_or_create_officers_parent_group )
187
+ end
188
+
189
+ def find_or_create_admins_parent_group
190
+ find_special_group(:admins_parent, parent_element: find_or_create_officers_parent_group) or
191
+ begin
192
+ delete_cached(:find_admins)
193
+ create_special_group(:admins_parent, parent_element: find_or_create_officers_parent_group)
194
+ rescue
195
+ nil
196
+ end
197
+ end
198
+
199
+ def admins_parent
200
+ find_or_create_admins_parent_group
201
+ end
202
+
203
+ def admins_parent!
204
+ find_admins_parent_group || raise('special group :admins_parent does not exist.')
205
+ end
206
+
207
+ def admins
208
+ find_or_create_admins_parent_group.try( :descendant_users ) || []
209
+ end
210
+
211
+ def find_admins
212
+ cached do
213
+ if respond_to? :child_groups
214
+ find_admins_parent_group.try( :descendant_users )
215
+ end || []
216
+ end || []
217
+ end
218
+
219
+ def admins_of_ancestors
220
+ cached { ancestors.collect { |ancestor| ancestor.find_admins }.flatten }
221
+ end
222
+
223
+ def admins_of_ancestor_groups
224
+ cached { ancestor_groups.collect { |ancestor| ancestor.find_admins }.flatten }
225
+ end
226
+
227
+ def admins_of_self_and_ancestors
228
+ cached { find_admins + admins_of_ancestors }
229
+ end
230
+
231
+
232
+ # Main Admins
233
+ # ==========================================================================================
234
+ #
235
+ # Main admins are also admins. But they have more rights and responsibilities.
236
+ # For example, they may edit the critical properties of the objects they administrate.
237
+ #
238
+ # Since main admins are also admins, the special group structure looks like this:
239
+ #
240
+ # my_structureable
241
+ # |----------- officers_parent
242
+ # |----------- admins_parent
243
+ # |---------- main_admins_parent
244
+ #
245
+ # One can access or assign the main admins of the structureable object by calling:
246
+ #
247
+ # my_structureable.main_admins # => Array of users
248
+ # my_structureable.main_admins << user
249
+ #
250
+
251
+ def find_main_admins_parent_group
252
+ find_special_group(:main_admins_parent, parent_element: find_admins_parent_group)
253
+ end
254
+
255
+ def create_main_admins_parent_group
256
+ create_special_group(:main_admins_parent, parent_element: find_or_create_admins_parent_group )
257
+ end
258
+
259
+ def find_or_create_main_admins_parent_group
260
+ find_or_create_special_group(:main_admins_parent, parent_element: find_or_create_admins_parent_group )
261
+ end
262
+
263
+ def main_admins_parent
264
+ find_or_create_main_admins_parent_group
265
+ end
266
+
267
+ def main_admins_parent!
268
+ find_main_admins_parent_group || raise('special group :main_admins_parent does not exist.')
269
+ end
270
+
271
+ def main_admins
272
+ main_admins_parent.descendant_users
273
+ end
274
+
275
+ end
@@ -0,0 +1,878 @@
1
+ # -*- coding: utf-8 -*-
2
+ class User < ActiveRecord::Base
3
+
4
+ attr_accessible :first_name, :last_name, :name, :alias, :email, :create_account, :female, :add_to_group,
5
+ :add_to_corporation, :date_of_birth, :localized_date_of_birth,
6
+ :aktivmeldungsdatum, :study_address, :home_address, :work_address, :phone, :mobile
7
+
8
+ attr_accessor :create_account, :add_to_group, :add_to_corporation
9
+ # Boolean, der vormerkt, ob dem (neuen) Benutzer ein Account hinzugefügt werden soll.
10
+
11
+ validates_presence_of :first_name, :last_name
12
+ validates_format_of :first_name, with: /^[^\,]*$/ # The name must not contain a comma.
13
+ validates_format_of :last_name, with: /^[^\,]*$/
14
+
15
+ validates_uniqueness_of :alias, :if => Proc.new { |user| user.account and user.alias.present? }
16
+ validates_format_of :email, :with => Devise::email_regexp, :if => Proc.new { |user| user.email.present? }, judge: :ignore
17
+
18
+ has_one :account, class_name: "UserAccount", autosave: true, inverse_of: :user, dependent: :destroy
19
+ validates_associated :account
20
+
21
+ delegate :send_welcome_email, :to => :account
22
+
23
+ is_structureable ancestor_class_names: %w(Page Group), descendant_class_names: %w(Page)
24
+
25
+ has_many :relationships_as_first_user, foreign_key: 'user1_id', class_name: "Relationship", dependent: :destroy, inverse_of: :user1
26
+
27
+ has_many :relationships_as_second_user, foreign_key: 'user2_id', class_name: "Relationship", dependent: :destroy, inverse_of: :user2
28
+
29
+ has_many :bookmarks
30
+ has_many :last_seen_activities
31
+
32
+ is_navable
33
+
34
+ before_save :generate_alias_if_necessary, :capitalize_name
35
+ before_save :build_account_if_requested
36
+ after_save :add_to_group_if_requested
37
+ after_save { self.delay.delete_cache }
38
+
39
+ # after_commit :delete_cache, prepend: true
40
+ # before_destroy :delete_cache, prepend: true
41
+
42
+
43
+ # Mixins
44
+ # ==========================================================================================
45
+
46
+ include UserMixins::Memberships
47
+ include UserMixins::Identification
48
+ include ProfileableMixins::Address
49
+ include UserCorporations
50
+ include UserProfile
51
+ include UserDateOfBirth
52
+ include UserAvatar
53
+
54
+ # General Properties
55
+ # ==========================================================================================
56
+
57
+ # The name of the user, i.e. first_name and last_name.
58
+ #
59
+ def name
60
+ first_name + " " + last_name if first_name && last_name
61
+ end
62
+
63
+ # This method will make the first_name and the last_name capitalized.
64
+ # For example:
65
+ #
66
+ # @user = User.create( first_name: "john", last_name: "doe", ... )
67
+ # @user.capitalize_name # => "John Doe"
68
+ # @user.save
69
+ # @user.name # => "John Doe"
70
+ #
71
+ def capitalize_name
72
+ self.first_name = capitalized_name_string( self.first_name )
73
+ self.last_name = capitalized_name_string( self.last_name )
74
+ self.name
75
+ end
76
+
77
+ def capitalized_name_string( name_string )
78
+ return name_string if name_string.include?( " " )
79
+ return name_string.slice( 0, 1 ).capitalize + name_string.slice( 1 .. -1 )
80
+ end
81
+ private :capitalized_name_string
82
+
83
+ # This method returns a kind of label for the user, e.g. for menu items representing the user.
84
+ # Use this rather than the name attribute itself, since the title method is likely to be overridden
85
+ # in the main application.
86
+ # Notice: This method does *not* return the academic title of the user.
87
+ #
88
+ def title
89
+ name
90
+ end
91
+
92
+ def name_affix
93
+ title.gsub(name, '').strip
94
+ end
95
+
96
+
97
+ # This sets the format of the User urls to be
98
+ #
99
+ # example.com/users/24-john-doe
100
+ #
101
+ # rather than just
102
+ #
103
+ # example.com/users/24
104
+ #
105
+ # This method uses a cache on purpose, since it is directly used by rails
106
+ # to construct the url.
107
+ #
108
+ def to_param
109
+ "#{id} #{title}".parameterize
110
+ end
111
+
112
+
113
+ # This accessors allow to access the gender of the user rather than just asking if the
114
+ # user is female as allowed by the ActiveRecord accessor.
115
+ # (:female is a boolean column in the users table.)
116
+ #
117
+ def gender
118
+ return :female if female?
119
+ return :male
120
+ end
121
+ def gender=( new_gender )
122
+ if new_gender.to_s == "female"
123
+ self.female = true
124
+ else
125
+ self.female = false
126
+ end
127
+ end
128
+ def male?
129
+ not female?
130
+ end
131
+
132
+
133
+ # Date of Death
134
+ # The date of death is localized already!
135
+ # Why?
136
+ #
137
+ def date_of_death
138
+ cached { profile_fields.where(label: 'date_of_death').first.try(:value) }
139
+ end
140
+
141
+ def set_date_of_death_if_unset(new_date_of_death)
142
+ new_date_of_death = I18n.localize(new_date_of_death.to_date)
143
+ unless self.date_of_death
144
+ profile_fields.create(type: "ProfileFieldTypes::General", label: 'date_of_death', value: new_date_of_death)
145
+ end
146
+ end
147
+ def dead?
148
+ date_of_death ? true : false
149
+ end
150
+ def alive?
151
+ not dead?
152
+ end
153
+
154
+ # Example:
155
+ #
156
+ # user.mark_as_deceased at: "2014-03-05".to_datetime
157
+ #
158
+ def mark_as_deceased(options = {})
159
+ date = options[:at] || Time.zone.now
160
+ self.current_corporations.each do |corporation|
161
+ self.current_status_membership_in(corporation).move_to corporation.deceased, at: date
162
+ end
163
+ end_all_non_corporation_memberships at: date
164
+ set_date_of_death_if_unset(date)
165
+ account.try(:destroy)
166
+ end
167
+
168
+ # Defines whether the user can be marked as deceased (by a workflow).
169
+ #
170
+ def markable_as_deceased?
171
+ alive?
172
+ end
173
+
174
+ def end_all_non_corporation_memberships(options = {})
175
+ date = options[:at] || Time.zone.now
176
+ for group in (self.direct_groups - Group.corporations_parent.descendant_groups)
177
+ UserGroupMembership.find_by_user_and_group(self, group).invalidate at: date
178
+ end
179
+ end
180
+
181
+ def postal_address_with_name_surrounding
182
+ address_label.to_s
183
+ end
184
+
185
+ def address_label
186
+ cached do
187
+ AddressLabel.new(self.name, self.postal_address_field_or_first_address_field,
188
+ self.name_surrounding_profile_field, self.personal_title, self.corporation_name)
189
+ end
190
+ end
191
+
192
+
193
+ # Associated Objects
194
+ # ==========================================================================================
195
+
196
+ # Alias
197
+ # ------------------------------------------------------------------------------------------
198
+
199
+ # The UserAlias class inherits from String, but has some more methods, e.g. a method
200
+ # to generate a new alias from other user attributes. To make sure that `alias` returns
201
+ # an object of UserAlias type, the accessor methods are overridden here.
202
+ #
203
+ def alias
204
+ UserAlias.new(super) if super.present?
205
+ end
206
+
207
+ def generate_alias
208
+ UserAlias.generate_for(self)
209
+ end
210
+
211
+ def generate_alias!
212
+ self.alias = self.generate_alias
213
+ end
214
+
215
+ def generate_alias_if_necessary
216
+ self.generate_alias! if self.account and self.alias.blank?
217
+ end
218
+ private :generate_alias_if_necessary
219
+
220
+
221
+ # User Account
222
+ # ------------------------------------------------------------------------------------------
223
+
224
+ # A user stored in the database does not necessarily possess the right to log in, i.e.
225
+ # have a user account. This method allows to find out whether the user has got an
226
+ # active user account.
227
+ #
228
+ def has_account?
229
+ return true if self.account
230
+ return false
231
+ end
232
+ def has_no_account?
233
+ not self.account.present?
234
+ end
235
+
236
+ # This method activates the user account, i.e. grants the user the right to log in.
237
+ #
238
+ def activate_account
239
+ unless self.account
240
+ self.account = self.build_account
241
+ self.save
242
+ end
243
+ return self.account
244
+ end
245
+
246
+ # This method deactivates the user account, i.e. destroys the associated object
247
+ # and prevents the user from logging in.
248
+ #
249
+ def deactivate_account
250
+ raise "no user account exists, therefore it can't be destroyed." if not self.account
251
+ self.account.destroy
252
+ self.account = nil
253
+ end
254
+
255
+ # If the attribute `create_account` is set to `true` or to `1`, e.g. by an html form,
256
+ # this code makes sure that the account association is build.
257
+ # This code is run on validation, as you can see above in this model.
258
+ # Note: A welcome email is automatically sent on save by the UserAccount model.
259
+ def build_account_if_requested
260
+
261
+ # If this value is set by an html form, it is "0" or "1". But "0" would
262
+ # transform to true rather than to false.
263
+ # Thus, we have to make sure that "0" means false.
264
+ self.create_account = false if self.create_account == "0"
265
+ self.create_account = true if self.create_account == "1"
266
+ self.create_account = false if self.create_account == 0
267
+ self.create_account = true if self.create_account == 1
268
+ self.create_account = false if self.create_account == ""
269
+
270
+ if self.create_account == true
271
+ self.account.destroy if self.has_account?
272
+ self.account = self.build_account
273
+ self.create_account = false # to make sure that this code is nut run twice.
274
+ return self.account
275
+ end
276
+
277
+ end
278
+ private :build_account_if_requested
279
+
280
+
281
+ # Activities
282
+ # ------------------------------------------------------------------------------------------
283
+
284
+ def find_or_build_last_seen_activity
285
+ last_seen_activities.last || last_seen_activities.build
286
+ end
287
+
288
+ def update_last_seen_activity(description = nil, object = nil)
289
+ unless readonly?
290
+ if description and not self.incognito?
291
+ activity = find_or_build_last_seen_activity
292
+ activity.touch # even if the attributes didn't change. The user probably hit 'reload' then.
293
+ activity.description = description
294
+ activity.link_to_object = object
295
+ activity.save
296
+ else
297
+ last_seen_activities.destroy_all
298
+ end
299
+ end
300
+ end
301
+
302
+ # Groups
303
+ # ------------------------------------------------------------------------------------------
304
+
305
+ def add_to_group_if_requested
306
+ if self.add_to_group
307
+ group = add_to_group if add_to_group.kind_of? Group
308
+ group = Group.find( add_to_group ) if add_to_group.to_i unless group
309
+ UserGroupMembership.create( user: self, group: group ) if group
310
+ end
311
+ if self.add_to_corporation.present?
312
+ corporation = add_to_corporation if add_to_corporation.kind_of? Group
313
+ corporation ||= Group.find(add_to_corporation) if add_to_corporation.kind_of? Fixnum
314
+ corporation ||= Group.find(add_to_corporation.to_i) if add_to_corporation.kind_of?(String) && add_to_corporation.to_i.kind_of?(Fixnum)
315
+ if corporation
316
+ status_group = corporation.becomes(Corporation).status_groups.first || raise('no status group in this corporation!')
317
+ status_group.assign_user self
318
+ else
319
+ raise 'corporation not found.'
320
+ end
321
+ end
322
+ end
323
+ private :add_to_group_if_requested
324
+
325
+
326
+ # Corporations
327
+ # ------------------------------------------------------------------------------------------
328
+
329
+ # This returns all corporations of the user. The Corporation model inherits from the Group
330
+ # model. corporations are child_groups of the corporations_parent_group in the DAG.
331
+ #
332
+ # everyone
333
+ # |----- corporations_parent
334
+ # | |---------- corporation_a <----
335
+ # | | |--- ... |--- These are corporations
336
+ # | |---------- corporation_b <----
337
+ # | |--- ...
338
+ # |----- other_group_1
339
+ # |----- other_group_2
340
+ #
341
+ # Warning!
342
+ # This method does not distinguish between regular members and guest members.
343
+ # If a user is only guest in a corporation, `user.corporations` WILL list this corporation.
344
+ #
345
+ def corporations
346
+ cached do
347
+ my_corporation_ids = (self.group_ids & Group.corporations.pluck(:id) ) if Group.corporations_parent
348
+ my_corporation_ids ||= []
349
+ Corporation.find my_corporation_ids
350
+ end
351
+ end
352
+
353
+ # This returns the corporations the user is currently member of.
354
+ #
355
+ def current_corporations
356
+ cached do
357
+ self.corporations.select do |corporation|
358
+ Role.of(self).in(corporation).current_member?
359
+ end || []
360
+ end
361
+ end
362
+
363
+ # This returns the same as `current_corporations`, but sorted by the
364
+ # date of joining the corporations, earliest joining first.
365
+ #
366
+ def sorted_current_corporations
367
+ cached do
368
+ current_corporations.sort_by do |corporation|
369
+ corporation.membership_of(self).valid_from || Time.zone.now - 100.years
370
+ end
371
+ end
372
+ end
373
+
374
+ # This returns the first corporation where the user is still member of or nil
375
+ #
376
+ def first_corporation
377
+ # if self.corporations
378
+ # self.corporations.select do |corporation|
379
+ # not ( self.guest_of?( corporation )) and
380
+ # not ( self.former_member_of_corporation?( corporation ))
381
+ # end.sort_by do |corporation|
382
+ # corporation.membership_of( self ).valid_from or Time.zone.now
383
+ # end.first
384
+ # end
385
+
386
+ sorted_current_corporations.first
387
+ end
388
+
389
+ # This returns the groups within the first corporation
390
+ # where the user is still member of in the order of entering the group.
391
+ # The groups must not be special and the user most not be a special member.
392
+ def my_groups_in_first_corporation
393
+ cached do
394
+ if first_corporation
395
+ my_memberships = UserGroupMembership.find_all_by_user( self )
396
+ my_memberships = my_memberships.now.reorder{ |membership| membership.valid_from }
397
+ my_groups = my_memberships.collect { |membership| membership.try( :group ) } if my_memberships
398
+ my_groups ||= []
399
+ my_groups.select do |group|
400
+ first_corporation.in?( group.ancestor_groups )
401
+ end.reject { |group| group.is_special_group? or self.guest_of?( group ) }
402
+ else
403
+ []
404
+ end
405
+ end
406
+ end
407
+
408
+ def last_group_in_first_corporation
409
+ my_groups_in_first_corporation.last
410
+ end
411
+
412
+
413
+ # Corporate Vita
414
+ # ==========================================================================================
415
+
416
+ def corporate_vita_memberships_in(corporation)
417
+ Rails.cache.fetch([self, 'corporate_vita_memberships_in', corporation], expires_in: 1.week) do
418
+ group_ids = corporation.status_groups.map(&:id) & self.parent_groups.map(&:id)
419
+ UserGroupMembership.now_and_in_the_past.find_all_by_user(self).where(ancestor_id: group_ids, ancestor_type: 'Group')
420
+ end
421
+ end
422
+
423
+
424
+ # Status Groups
425
+ # ------------------------------------------------------------------------------------------
426
+
427
+ # This returns all status groups of the user, i.e. groups that represent the member
428
+ # status of the user in a corporation.
429
+ #
430
+ # options:
431
+ # :with_invalid => true, false
432
+ #
433
+ def status_groups(options = {})
434
+ StatusGroup.find_all_by_user(self, options)
435
+ end
436
+
437
+ def status_group_memberships
438
+ self.status_groups.collect do |group|
439
+ StatusGroupMembership.find_by_user_and_group( self, group )
440
+ end
441
+ end
442
+
443
+ def current_status_membership_in( corporation )
444
+ if status_group = current_status_group_in(corporation)
445
+ StatusGroupMembership.find_by_user_and_group(self, status_group)
446
+ end
447
+ end
448
+
449
+ def current_status_group_in(corporation)
450
+ StatusGroup.find_by_user_and_corporation(self, corporation) if corporation
451
+ end
452
+
453
+ def status_group_in_primary_corporation
454
+ # - First try the `first_corporation`, which does not consider corporations the user is
455
+ # a former member of.
456
+ # - Next, use all corporations, which applies to completely excluded members.
457
+ #
458
+ cached { current_status_group_in(first_corporation || corporations.first) }
459
+ end
460
+
461
+
462
+ # Relationships
463
+ # ------------------------------------------------------------------------------------------
464
+
465
+ # This returns all relationship opjects.
466
+ #
467
+ def relationships
468
+ relationships_as_first_user + relationships_as_second_user
469
+ end
470
+
471
+
472
+ # Workflows
473
+ # ------------------------------------------------------------------------------------------
474
+
475
+ # This method returns all workflows applicable for this user, i.e. this returns
476
+ # all workflows of all groups the user is a member of.
477
+ #
478
+ def workflows
479
+ my_workflows = []
480
+ self.groups.each do |group|
481
+ my_workflows += group.child_workflows
482
+ end
483
+ return my_workflows
484
+ end
485
+
486
+ def workflows_for(group)
487
+ (([group.becomes(Group)] + group.descendant_groups) & self.groups)
488
+ .collect { |g| g.child_workflows }.select { |w| not w.nil? }.flatten
489
+ end
490
+
491
+ def workflows_by_corporation
492
+ hash = {}
493
+ other_workflows = self.workflows
494
+ self.corporations.each do |corporation|
495
+ corporation_workflows = self.workflows_for(corporation)
496
+ hash.merge!( corporation.title.to_s => corporation_workflows )
497
+ other_workflows -= corporation_workflows
498
+ end
499
+ hash.merge!( I18n.t(:others).to_s => other_workflows ) if other_workflows.count > 0
500
+ return hash
501
+ end
502
+
503
+ # Events
504
+ # ------------------------------------------------------------------------------------------
505
+
506
+ # This method lists all upcoming events of the groups the user is member of.
507
+ #
508
+ def upcoming_events
509
+ Event.upcoming.find_all_by_groups( self.groups ).direct
510
+ end
511
+
512
+ # This makes the user join an event or a grop.
513
+ #
514
+ def join(event_or_group)
515
+ if event_or_group.kind_of? Group
516
+ event_or_group.assign_user self
517
+ elsif event_or_group.kind_of? Event
518
+ event_or_group.attendees_group.assign_user self
519
+ end
520
+ end
521
+ def leave(event_or_group)
522
+ if event_or_group.kind_of? Group
523
+ # TODO: Change to `unassign` when he can have multiple dag links between two nodes.
524
+ # event_or_group.members.destroy(self)
525
+ raise 'We need multiple dag links between two nodes!'
526
+ elsif event_or_group.kind_of? Event
527
+ # TODO: Change to `unassign` when he can have multiple dag links between two nodes.
528
+ event_or_group.attendees_group.members.destroy(self)
529
+ end
530
+ end
531
+
532
+
533
+ # News Entries (Pages)
534
+ # -------------------
535
+
536
+ # List news (Pages) that concern the user.
537
+ #
538
+ # everyone ---- page_1 ---- page_2 <--- show
539
+ # |
540
+ # |----- group_1 ---- page_3 <--- DO NOT show
541
+ # |
542
+ # |----- group_2 ---- user
543
+ # | |-- page_4 <--- show
544
+ # |
545
+ # |--- user
546
+ #
547
+ def news_pages
548
+ # List all pages that do not have ancestor groups
549
+ # which the user is no member of.
550
+ #
551
+
552
+ # THIS WORKS BUT LOOKS UGLY. TODO: Refactor this:
553
+ group_ids_the_user_is_no_member_of =
554
+ Group.pluck(:id) - self.group_ids
555
+ pages_that_belong_to_groups_the_user_is_no_member_of = Page
556
+ .includes(:ancestor_groups)
557
+ .where(groups: {id: group_ids_the_user_is_no_member_of})
558
+ Page
559
+ .where('NOT id IN (?)', (pages_that_belong_to_groups_the_user_is_no_member_of + [0])) # +[0]-hack: otherwise the list is empty when all pages should be shown, i.e. for fresh systems.
560
+ .order('pages.updated_at DESC')
561
+ end
562
+
563
+
564
+ # Bookmarked Objects
565
+ # ------------------------------------------------------------------------------------------
566
+
567
+ # This method lists all bookmarked objets of this user.
568
+ #
569
+ def bookmarked_objects
570
+ self.bookmarks.collect { |bookmark| bookmark.bookmarkable }
571
+ end
572
+
573
+
574
+ # Roles and Rights
575
+ # ==========================================================================================
576
+
577
+ # This method returns the role the user (self) has for a given
578
+ # structureable object.
579
+ #
580
+ # The roles may be :member, :admin or :main_admin.
581
+ #
582
+ def role_for( structureable )
583
+ return nil if not structureable.respond_to? :parent_groups
584
+ return :main_admin if self.main_admin_of? structureable
585
+ return :admin if self.admin_of? structureable
586
+ return :member if self.member_of? structureable
587
+ end
588
+
589
+ # Member Status
590
+ # ------------------------------------------------------------------------------------------
591
+
592
+ # This method is a dirty hack to preserve the obsolete role model mechanism,
593
+ # which is currently not in use, since the abilities are defined directly in the
594
+ # Ability class.
595
+ #
596
+ # Options:
597
+ #
598
+ # with_invalid, also_in_the_past : true/false
599
+ #
600
+ # TODO: refactor it together with the role model mechanism.
601
+ #
602
+ def member_of?( object, options = {} )
603
+ if object.kind_of? Group
604
+ if options[:with_invalid] or options[:also_in_the_past]
605
+ self.ancestor_group_ids.include? object.id
606
+ else # only current memberships:
607
+ self.group_ids.include? object.id # This uses the validity range mechanism
608
+ end
609
+ else
610
+ self.ancestors.include? object
611
+ end
612
+ end
613
+
614
+ # Admins
615
+ # ------------------------------------------------------------------------------------------
616
+
617
+ def admin_of_anything?
618
+ groups.find_all_by_flag(:admins_parent).count > 0
619
+ end
620
+
621
+ # This method finds all objects the user is an administrator of.
622
+ #
623
+ def admin_of
624
+ self.administrated_objects
625
+ end
626
+
627
+ # This method verifies if the user is administrator of the given structureable object.
628
+ #
629
+ def admin_of?( structureable )
630
+ self.admin_of.include? structureable
631
+ end
632
+
633
+ # This method returns all structureable objects the user is directly administrator of,
634
+ # i.e. the user is a member of the administrators group of this object.
635
+ #
636
+ def directly_administrated_objects( role = :admin )
637
+ admin_group_flag = :admins_parent if role == :admin
638
+ admin_group_flag = :main_admins_parent if role == :main_admin
639
+ admin_groups = self.ancestor_groups.find_all_by_flag( admin_group_flag )
640
+ if admin_groups.count > 0
641
+ objects = admin_groups.collect do |admin_group|
642
+ admin_group.administrated_object
643
+ end
644
+ else
645
+ []
646
+ end
647
+ end
648
+
649
+ # This method returns all structureable objects the user is administrator of.
650
+ #
651
+ def administrated_objects( role = :admin )
652
+ objects = directly_administrated_objects( role )
653
+ if objects
654
+ objects += objects.collect do |directly_administrated_object|
655
+ directly_administrated_object.descendants
656
+ end.flatten
657
+ objects
658
+ else
659
+ []
660
+ end
661
+ end
662
+
663
+ # Main Admins
664
+ # ------------------------------------------------------------------------------------------
665
+
666
+ # This method says whether the user (self) is a main admin of the given
667
+ # structureable object.
668
+ #
669
+ def main_admin_of?( structureable )
670
+ self.administrated_objects( :main_admin ).include? structureable
671
+ end
672
+
673
+
674
+ # Guest Status
675
+ # ==========================================================================================
676
+
677
+ # This method says if the user (self) is a guest of the given group.
678
+ #
679
+ def guest_of?( group )
680
+ return false if not group.find_guests_parent_group
681
+ group.guests.include? self
682
+ end
683
+
684
+ # Developer Status
685
+ # ==========================================================================================
686
+
687
+ # This method returns whether the user is a developer. This is needed, for example,
688
+ # to determine if some features are presented to the current_user.
689
+ #
690
+ def developer?
691
+ self.developer
692
+ end
693
+ def developer
694
+ self.member_of? Group.developers
695
+ end
696
+ def developer=( mark_as_developer )
697
+ if mark_as_developer
698
+ Group.developers.assign_user self
699
+ else
700
+ Group.developers.unassign_user self
701
+ end
702
+ end
703
+
704
+ # Hidden
705
+ # ==========================================================================================
706
+ #
707
+ # Some users are hidden for regular users. They can only be seen by their administrators.
708
+ # This is necessary for some organizations due to privacy reasons.
709
+ #
710
+
711
+ def hidden?
712
+ self.hidden
713
+ end
714
+
715
+ def hidden
716
+ cached { self.member_of? Group.hidden_users }
717
+ end
718
+
719
+ def hidden=(hidden)
720
+ Group.hidden_users.assign_user self if hidden == true || hidden == "true"
721
+ Group.hidden_users.unassign_user self if hidden == false || hidden == "false"
722
+ end
723
+
724
+ def self.find_all_hidden
725
+ self.where(id: Group.hidden_users.member_ids)
726
+ end
727
+
728
+ def self.find_all_non_hidden
729
+ non_hidden_user_ids = User.pluck(:id) - Group.hidden_users.member_ids
730
+ self.where(id: non_hidden_user_ids) # in order to make it work with cancan.
731
+ end
732
+
733
+ # Former Member
734
+ # ==========================================================================================
735
+
736
+ def former_member_of_corporation?( corporation )
737
+ corporation.becomes(Corporation).former_members.include? self
738
+ end
739
+
740
+
741
+ # Group Flags
742
+ # ==========================================================================================
743
+
744
+ # This efficiently returns all flags of the groups the user is currently in.
745
+ #
746
+ # For example, ony can find out with one sql query whether a user is hidden:
747
+ #
748
+ # user.group_flags.include? 'hidden_users'
749
+ #
750
+ def group_flags
751
+ groups.joins(:flags).pluck('flags.key')
752
+ end
753
+
754
+
755
+ # Global Admin Switch
756
+ # ==========================================================================================
757
+
758
+ def global_admin
759
+ self.in? Group.everyone.admins
760
+ end
761
+ def global_admin?
762
+ self.global_admin
763
+ end
764
+ def global_admin=(new_setting)
765
+ if new_setting == true
766
+ Group.everyone.admins << self
767
+ else
768
+ UserGroupMembership.find_by_user_and_group(self, Group.everyone.main_admins_parent).try(:destroy)
769
+ UserGroupMembership.find_by_user_and_group(self, Group.everyone.admins_parent).try(:destroy)
770
+ end
771
+ end
772
+
773
+
774
+
775
+ # Finder Methods
776
+ # ==========================================================================================
777
+
778
+ # This method returns the first user matching the given title.
779
+ #
780
+ def self.find_by_title( title )
781
+ self.where("? LIKE CONCAT('%', first_name, ' ', last_name, '%')", title).select do |user|
782
+ user.title == title
783
+ end.first
784
+ end
785
+
786
+ def self.find_by_name( name )
787
+ self.find_all_by_name(name).limit(1).first
788
+ end
789
+
790
+ # This method finds all users having the given name attribute.
791
+ # notice: case insensitive
792
+ #
793
+ def self.find_all_by_name( name ) # TODO: Test this
794
+ self.where("CONCAT(first_name, ' ', last_name) = ?", name)
795
+ end
796
+
797
+ # This method finds all users having the given email attribute.
798
+ # notice: case insensitive
799
+ #
800
+ def self.find_all_by_email( email ) # TODO: Test this; # TODO: optimize using where
801
+ email_fields = ProfileField.where( type: "ProfileFieldTypes::Email", value: email )
802
+ matching_users = email_fields
803
+ .select{ |ef| ef.profileable_type == "User" }
804
+ .collect { |ef| ef.profileable }
805
+ return matching_users.to_a
806
+ end
807
+
808
+ def self.find_by_email( email )
809
+ self.find_all_by_email(email).first
810
+ end
811
+
812
+ def self.with_group_flags
813
+ self.joins(:groups => :flags)
814
+ end
815
+
816
+ def self.with_group_flag(flag)
817
+ self.with_group_flags.where("flags.key = ?", flag)
818
+ end
819
+
820
+ def self.hidden
821
+ self.with_group_flag('hidden_users')
822
+ end
823
+
824
+ def self.deceased
825
+ self.joins(:profile_fields).where(:profile_fields => {label: 'date_of_death'})
826
+ end
827
+
828
+ def self.deceased_ids
829
+ self.deceased.pluck(:id)
830
+ end
831
+
832
+ def self.alive
833
+ if self.deceased_ids.count > 0
834
+ self.where('NOT users.id IN (?)', self.deceased_ids)
835
+ else
836
+ self.where(true)
837
+ end
838
+ end
839
+
840
+ def self.without_account
841
+ self.includes(:account).where(:user_accounts => { :user_id => nil })
842
+ end
843
+
844
+ def self.with_email
845
+ self.joins(:profile_fields).where('profile_fields.type = ? AND profile_fields.value != ?', 'ProfileFieldTypes::Email', '')
846
+ end
847
+
848
+ def self.applicable_for_new_account
849
+ self.alive.without_account.with_email
850
+ end
851
+
852
+ def self.joins_groups
853
+ self.joins(:groups).where('dag_links.valid_to IS NULL')
854
+ end
855
+
856
+ def accept_terms(terms_stamp)
857
+ self.accepted_terms = terms_stamp
858
+ self.accepted_terms_at = Time.zone.now
859
+ save!
860
+ end
861
+ def accepted_terms?(terms_stamp)
862
+ self.accepted_terms == terms_stamp
863
+ end
864
+
865
+ # Helpers
866
+ # ==========================================================================================
867
+
868
+ # The string returned by this method represents the user in the rails console.
869
+ # For example, if you type `User.all` in the console, the answer would be:
870
+ #
871
+ # User: alias_of_the_first_user, User: alias_of_the_second_user, ...
872
+ #
873
+ def inspect
874
+ "User: #{self.id} #{self.alias}"
875
+ end
876
+
877
+ end
878
+