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.
- checksums.yaml +7 -0
- data/README.md +39 -11
- data/Rakefile +15 -1
- data/app/assets/images/file.png +0 -0
- data/app/assets/images/img/excel2013_file_128.png +0 -0
- data/app/assets/images/img/excel2013_file_bw_107.png +0 -0
- data/app/assets/images/img/excel2013_file_bw_semitransparent_107.png +0 -0
- data/app/assets/images/img/glyphicons-halflings-white.png +0 -0
- data/app/assets/images/img/glyphicons-halflings.png +0 -0
- data/app/assets/images/img/gmaps_yellow_marker.png +0 -0
- data/app/assets/images/img/gmaps_yellow_marker_38.png +0 -0
- data/app/assets/images/markdown_help.png +0 -0
- data/app/assets/images/your_platform/breadcrumb-sep.png +0 -0
- data/app/assets/javascripts/app-ng.js.coffee +5 -0
- data/app/assets/javascripts/attachments.js +2 -0
- data/app/assets/javascripts/controllers-ng/bookmark_list_controller.js.coffee +30 -0
- data/app/assets/javascripts/controllers-ng/box_controller.js.coffee +37 -0
- data/app/assets/javascripts/controllers-ng/profile_angular.js.coffee +151 -0
- data/app/assets/javascripts/directives-ng/box_directive.js.coffee +91 -0
- data/app/assets/javascripts/directives-ng/star_tool_directive.js.coffee +111 -0
- data/app/assets/javascripts/filters-ng/some_filter.js.coffee +0 -0
- data/app/assets/javascripts/jquery.appear-1.1.1.js +138 -0
- data/app/assets/javascripts/make-js-more-like-ruby.js.coffee +32 -0
- data/app/assets/javascripts/mercury.js +456 -0
- data/app/assets/javascripts/models-ng/bookmark.js.coffee +28 -0
- data/app/assets/javascripts/services-ng/current_user_bookmarks.js.coffee +39 -0
- data/app/assets/javascripts/your_platform.js +27 -0
- data/app/assets/javascripts/your_platform/address_labels.js.coffee +40 -0
- data/app/assets/javascripts/your_platform/attachments.js.coffee +61 -0
- data/app/assets/javascripts/your_platform/auto-completion.js.coffee +90 -0
- data/app/assets/javascripts/your_platform/best_in_place.js.coffee +8 -0
- data/app/assets/javascripts/your_platform/best_in_place_hyperlinks.js.coffee +25 -0
- data/app/assets/javascripts/your_platform/best_in_place_tab_key.js.coffee +28 -0
- data/app/assets/javascripts/your_platform/boxes.js.coffee +11 -0
- data/app/assets/javascripts/your_platform/change_password.js.coffee +22 -0
- data/app/assets/javascripts/your_platform/close_dropdowns.js.coffee +18 -0
- data/app/assets/javascripts/your_platform/copy_to_clipboard.js.coffee +6 -0
- data/app/assets/javascripts/your_platform/datatables.coffee +112 -0
- data/app/assets/javascripts/your_platform/datepicker_settings.js.coffee +16 -0
- data/app/assets/javascripts/your_platform/edit_tools.js.coffee +19 -0
- data/app/assets/javascripts/your_platform/editable_dbl_click.js.coffee +42 -0
- data/app/assets/javascripts/your_platform/events.js.coffee +126 -0
- data/app/assets/javascripts/your_platform/fix_textarea.js.coffee +11 -0
- data/app/assets/javascripts/your_platform/galleria.js.coffee +112 -0
- data/app/assets/javascripts/your_platform/groups.js.coffee +36 -0
- data/app/assets/javascripts/your_platform/hidden.js.coffee +5 -0
- data/app/assets/javascripts/your_platform/links_to_external_sites.js.coffee +12 -0
- data/app/assets/javascripts/your_platform/maps.js.coffee +13 -0
- data/app/assets/javascripts/your_platform/may_need_review.js.coffee +10 -0
- data/app/assets/javascripts/your_platform/navable_title_rename.js.coffee +17 -0
- data/app/assets/javascripts/your_platform/officers.js.coffee +35 -0
- data/app/assets/javascripts/your_platform/popovers.js.coffee +38 -0
- data/app/assets/javascripts/your_platform/posts.js.coffee +58 -0
- data/app/assets/javascripts/your_platform/profile_fields.js.coffee +61 -0
- data/app/assets/javascripts/your_platform/search.js.coffee +26 -0
- data/app/assets/javascripts/your_platform/tooltips.js.coffee +10 -0
- data/app/assets/javascripts/your_platform/turbolinks_loading_spinner.js.coffee +83 -0
- data/app/assets/javascripts/your_platform/user_avatars.js.coffee +33 -0
- data/app/assets/javascripts/your_platform/user_group_memberships.js.coffee +11 -0
- data/app/assets/javascripts/your_platform/user_settings.js.coffee +18 -0
- data/app/assets/javascripts/your_platform/users_new.js.coffee +54 -0
- data/app/assets/stylesheets/bootstrap_layout.css.sass +3 -0
- data/app/assets/stylesheets/bootstrap_layout/attachments.css.sass +3 -0
- data/app/assets/stylesheets/bootstrap_layout/boxes.css.sass +11 -0
- data/app/assets/stylesheets/bootstrap_layout/breadcrumb.css.sass +25 -0
- data/app/assets/stylesheets/bootstrap_layout/category_indicator.css.sass +5 -0
- data/app/assets/stylesheets/bootstrap_layout/footer.css.sass +14 -0
- data/app/assets/stylesheets/bootstrap_layout/galleria.css.sass +8 -0
- data/app/assets/stylesheets/bootstrap_layout/header_bar.css.sass +11 -0
- data/app/assets/stylesheets/bootstrap_layout/headings.css.sass +10 -0
- data/app/assets/stylesheets/bootstrap_layout/logged_in_bar.css.sass +40 -0
- data/app/assets/stylesheets/bootstrap_layout/logo.css.sass +2 -0
- data/app/assets/stylesheets/bootstrap_layout/modal_fix.css.sass +8 -0
- data/app/assets/stylesheets/bootstrap_layout/profiles.css.sass +10 -0
- data/app/assets/stylesheets/bootstrap_layout/session_bar.css.sass +60 -0
- data/app/assets/stylesheets/bootstrap_layout/stars.css.sass +4 -0
- data/app/assets/stylesheets/bootstrap_layout/turbolinks_progress_bar.css.sass +3 -0
- data/app/assets/stylesheets/bootstrap_layout/vertical_menu.css.sass +15 -0
- data/app/assets/stylesheets/bootstrap_setup.css.sass +4 -0
- data/app/assets/stylesheets/your_platform.css.sass +11 -0
- data/app/assets/stylesheets/your_platform/address_labels_modal.css.sass +8 -0
- data/app/assets/stylesheets/your_platform/attachments.css.sass +75 -0
- data/app/assets/stylesheets/your_platform/authorization_info.css.sass +16 -0
- data/app/assets/stylesheets/your_platform/auto-completion.css.sass +3 -0
- data/app/assets/stylesheets/your_platform/center.css.sass +14 -0
- data/app/assets/stylesheets/your_platform/change_password.css.sass +13 -0
- data/app/assets/stylesheets/your_platform/corporate_vita.css.sass +2 -0
- data/app/assets/stylesheets/your_platform/datatables.css.sass +23 -0
- data/app/assets/stylesheets/your_platform/datepicker.css.sass +2 -0
- data/app/assets/stylesheets/your_platform/dropdowns.css.sass +8 -0
- data/app/assets/stylesheets/your_platform/events.css.sass +68 -0
- data/app/assets/stylesheets/your_platform/forms.css.sass +25 -0
- data/app/assets/stylesheets/your_platform/galleria.css.sass +12 -0
- data/app/assets/stylesheets/your_platform/groups.css.sass +8 -0
- data/app/assets/stylesheets/your_platform/groups_table.css.sass +8 -0
- data/app/assets/stylesheets/your_platform/hidden.css.sass +3 -0
- data/app/assets/stylesheets/your_platform/images.css.sass +50 -0
- data/app/assets/stylesheets/your_platform/last_activities.css.sass +17 -0
- data/app/assets/stylesheets/your_platform/latest_members.css.sass +7 -0
- data/app/assets/stylesheets/your_platform/login.css.sass +4 -0
- data/app/assets/stylesheets/your_platform/maps.css.sass +22 -0
- data/app/assets/stylesheets/your_platform/markdown_help.css.sass +5 -0
- data/app/assets/stylesheets/your_platform/may_need_review.css.sass +3 -0
- data/app/assets/stylesheets/your_platform/pages.css.sass +12 -0
- data/app/assets/stylesheets/your_platform/password_strength.css.sass +73 -0
- data/app/assets/stylesheets/your_platform/picture_attachments.css.sass +7 -0
- data/app/assets/stylesheets/your_platform/popovers.css.sass +13 -0
- data/app/assets/stylesheets/your_platform/posts.css.sass +32 -0
- data/app/assets/stylesheets/your_platform/profiles.css.sass +153 -0
- data/app/assets/stylesheets/your_platform/search_preview.css.sass +4 -0
- data/app/assets/stylesheets/your_platform/star_tool.css.sass +2 -0
- data/app/assets/stylesheets/your_platform/tooltips.css.sass +7 -0
- data/app/assets/stylesheets/your_platform/turbolinks_loading_spinner.css.sass +3 -0
- data/app/assets/stylesheets/your_platform/user_avatars.css.sass +8 -0
- data/app/assets/stylesheets/your_platform/user_group_memberships.css.sass +4 -0
- data/app/assets/stylesheets/your_platform/vertical_nav.css.sass +7 -0
- data/app/controllers/activities_controller.rb +6 -0
- data/app/controllers/application_controller.rb +236 -0
- data/app/controllers/attachments_controller.rb +97 -0
- data/app/controllers/blog_posts_controller.rb +50 -0
- data/app/controllers/bookmarks_controller.rb +33 -0
- data/app/controllers/corporations_controller.rb +22 -0
- data/app/controllers/errors_controller.rb +27 -0
- data/app/controllers/events_controller.rb +262 -0
- data/app/controllers/groups_controller.rb +257 -0
- data/app/controllers/officers_controller.rb +28 -0
- data/app/controllers/pages_controller.rb +67 -0
- data/app/controllers/posts_controller.rb +81 -0
- data/app/controllers/profile_fields_controller.rb +132 -0
- data/app/controllers/root_controller.rb +35 -0
- data/app/controllers/search_controller.rb +149 -0
- data/app/controllers/sessions_controller.rb +21 -0
- data/app/controllers/setup_controller.rb +80 -0
- data/app/controllers/statistics_controller.rb +38 -0
- data/app/controllers/status_group_memberships_controller.rb +28 -0
- data/app/controllers/terms_of_use_controller.rb +35 -0
- data/app/controllers/user_accounts_controller.rb +55 -0
- data/app/controllers/user_group_memberships_controller.rb +75 -0
- data/app/controllers/user_settings_controller.rb +57 -0
- data/app/controllers/users_controller.rb +125 -0
- data/app/controllers/workflows_controller.rb +19 -0
- data/app/helpers/application_helper.rb +25 -0
- data/app/helpers/attachments_helper.rb +2 -0
- data/app/helpers/auto_completion_helper.rb +33 -0
- data/app/helpers/avatar_helper.rb +70 -0
- data/app/helpers/bookmarks_helper.rb +22 -0
- data/app/helpers/box_helper.rb +56 -0
- data/app/helpers/breadcrumbs_helper.rb +62 -0
- data/app/helpers/corporate_vita_helper.rb +34 -0
- data/app/helpers/events_helper.rb +28 -0
- data/app/helpers/flash_helper.rb +60 -0
- data/app/helpers/footer_helper.rb +13 -0
- data/app/helpers/galleria_helper.rb +13 -0
- data/app/helpers/groups_helper.rb +66 -0
- data/app/helpers/horizontal_nav_helper.rb +11 -0
- data/app/helpers/i18n_helper.rb +10 -0
- data/app/helpers/icon_helper.rb +35 -0
- data/app/helpers/mailer_helper.rb +7 -0
- data/app/helpers/map_helper.rb +26 -0
- data/app/helpers/markdown_helper.rb +22 -0
- data/app/helpers/markup_helper.rb +25 -0
- data/app/helpers/officers_helper.rb +13 -0
- data/app/helpers/password_helper.rb +23 -0
- data/app/helpers/profile_field_helper.rb +40 -0
- data/app/helpers/profile_helper.rb +69 -0
- data/app/helpers/quick_link_helper.rb +53 -0
- data/app/helpers/special_pages_helper.rb +9 -0
- data/app/helpers/structureable_helper.rb +11 -0
- data/app/helpers/sublime_helper.rb +16 -0
- data/app/helpers/title_helper.rb +52 -0
- data/app/helpers/tool_buttons_helper.rb +74 -0
- data/app/helpers/unicode_helper.rb +9 -0
- data/app/helpers/users_helper.rb +13 -0
- data/app/helpers/vertical_nav_helper.rb +84 -0
- data/app/helpers/workflows_helper.rb +37 -0
- data/app/mailers/event_mailer.rb +13 -0
- data/app/mailers/post_mailer.rb +11 -0
- data/app/mailers/user_account_mailer.rb +17 -0
- data/app/models/ability.rb +321 -0
- data/app/models/active_record_associations_patches.rb +26 -0
- data/app/models/active_record_cache_extension.rb +152 -0
- data/app/models/active_record_find_by_extension.rb +20 -0
- data/app/models/active_record_json_url_extension.rb +51 -0
- data/app/models/active_record_metric_events_extension.rb +22 -0
- data/app/models/active_record_read_only_extension.rb +35 -0
- data/app/models/active_record_update_attributes_bip_extension.rb +24 -0
- data/app/models/address_label.rb +50 -0
- data/app/models/app_version.rb +49 -0
- data/app/models/array.rb +15 -0
- data/app/models/attachment.rb +76 -0
- data/app/models/bashpass_password.rb +32 -0
- data/app/models/blog_post.rb +2 -0
- data/app/models/bookmark.rb +67 -0
- data/app/models/cache_additions.rb +15 -0
- data/app/models/cache_store_extension.rb +78 -0
- data/app/models/concerns/user_avatar.rb +16 -0
- data/app/models/concerns/user_corporations.rb +44 -0
- data/app/models/concerns/user_date_of_birth.rb +74 -0
- data/app/models/concerns/user_profile.rb +102 -0
- data/app/models/corporation.rb +80 -0
- data/app/models/dag_link.rb +29 -0
- data/app/models/event.rb +235 -0
- data/app/models/flag.rb +18 -0
- data/app/models/flagable.rb +62 -0
- data/app/models/geo_location.rb +92 -0
- data/app/models/group.rb +224 -0
- data/app/models/group_mixins/corporations.rb +141 -0
- data/app/models/group_mixins/developers.rb +41 -0
- data/app/models/group_mixins/everyone.rb +72 -0
- data/app/models/group_mixins/guests.rb +61 -0
- data/app/models/group_mixins/hidden_users.rb +43 -0
- data/app/models/group_mixins/import.rb +321 -0
- data/app/models/group_mixins/memberships.rb +207 -0
- data/app/models/group_mixins/officers.rb +47 -0
- data/app/models/group_mixins/roles.rb +41 -0
- data/app/models/horizontal_nav.rb +32 -0
- data/app/models/last_seen_activity.rb +10 -0
- data/app/models/list_export.rb +359 -0
- data/app/models/may_need_review.rb +54 -0
- data/app/models/metric_logger.rb +83 -0
- data/app/models/nav_node.rb +169 -0
- data/app/models/navable.rb +46 -0
- data/app/models/object_to_b_extension.rb +12 -0
- data/app/models/page.rb +212 -0
- data/app/models/password.rb +28 -0
- data/app/models/post.rb +199 -0
- data/app/models/profile.rb +36 -0
- data/app/models/profile_field.rb +196 -0
- data/app/models/profile_field_mixins/has_child_profile_fields.rb +114 -0
- data/app/models/profile_field_types/about.rb +9 -0
- data/app/models/profile_field_types/academic_degree.rb +10 -0
- data/app/models/profile_field_types/address.rb +88 -0
- data/app/models/profile_field_types/bank_account.rb +12 -0
- data/app/models/profile_field_types/competence.rb +7 -0
- data/app/models/profile_field_types/custom.rb +12 -0
- data/app/models/profile_field_types/date.rb +14 -0
- data/app/models/profile_field_types/description.rb +15 -0
- data/app/models/profile_field_types/email.rb +20 -0
- data/app/models/profile_field_types/employment.rb +24 -0
- data/app/models/profile_field_types/general.rb +9 -0
- data/app/models/profile_field_types/homepage.rb +19 -0
- data/app/models/profile_field_types/name_surrounding.rb +11 -0
- data/app/models/profile_field_types/organization.rb +24 -0
- data/app/models/profile_field_types/phone.rb +37 -0
- data/app/models/profile_field_types/professional_category.rb +8 -0
- data/app/models/profile_field_types/study.rb +18 -0
- data/app/models/profile_section.rb +49 -0
- data/app/models/profileable.rb +58 -0
- data/app/models/profileable_mixins/address.rb +118 -0
- data/app/models/relationship.rb +78 -0
- data/app/models/role.rb +164 -0
- data/app/models/setting.rb +9 -0
- data/app/models/status_group.rb +28 -0
- data/app/models/status_group_membership.rb +189 -0
- data/app/models/status_group_membership_info.rb +54 -0
- data/app/models/structureable.rb +164 -0
- data/app/models/structureable_mixins/has_special_groups.rb +127 -0
- data/app/models/structureable_mixins/roles.rb +275 -0
- data/app/models/user.rb +878 -0
- data/app/models/user_account.rb +162 -0
- data/app/models/user_alias.rb +112 -0
- data/app/models/user_group_membership.rb +300 -0
- data/app/models/user_group_membership_mixins/validity_range.rb +206 -0
- data/app/models/user_group_membership_mixins/validity_range_for_indirect_memberships.rb +160 -0
- data/app/models/user_mixins/identification.rb +36 -0
- data/app/models/user_mixins/memberships.rb +75 -0
- data/app/models/workflow.rb +40 -0
- data/app/models/workflow_kit/add_to_group_brick.rb +21 -0
- data/app/models/workflow_kit/destroy_account_and_end_memberships_if_needed_brick.rb +19 -0
- data/app/models/workflow_kit/last_membership_needs_review_brick.rb +19 -0
- data/app/models/workflow_kit/mark_as_deceased_brick.rb +17 -0
- data/app/models/workflow_kit/remove_from_group_brick.rb +27 -0
- data/app/models/workflow_kit/test_brick.rb +13 -0
- data/app/pdfs/address_labels_pdf.rb +157 -0
- data/app/presenters/base_presenter.rb +52 -0
- data/app/presenters/horizontal_nav_presenter.rb +106 -0
- data/app/uploaders/attachment_uploader.rb +148 -0
- data/app/views/activities/index.html.haml +25 -0
- data/app/views/attachments/_attachment.html.haml +20 -0
- data/app/views/attachments/_description.html.haml +11 -0
- data/app/views/attachments/_documents.html.haml +17 -0
- data/app/views/attachments/_drop_field.html.haml +46 -0
- data/app/views/attachments/_picture.html.haml +2 -0
- data/app/views/attachments/_pictures.html.haml +10 -0
- data/app/views/attachments/_video.html.haml +8 -0
- data/app/views/attachments/create.js.erb +1 -0
- data/app/views/attachments/destroy.js.erb +1 -0
- data/app/views/blog_posts/create.js.erb +17 -0
- data/app/views/bookmarks/_list.html.haml +7 -0
- data/app/views/bookmarks/update.js.erb +4 -0
- data/app/views/devise/mailer/reset_password_instructions.html.haml +8 -0
- data/app/views/devise/passwords/edit.html.haml +1 -0
- data/app/views/devise/passwords/new.html.haml +12 -0
- data/app/views/devise/registrations/edit.html.haml +1 -0
- data/app/views/devise/sessions/new.html.haml +14 -0
- data/app/views/devise/shared/_links.haml +26 -0
- data/app/views/errors/show.html.haml +5 -0
- data/app/views/errors/unauthorized.html.haml +7 -0
- data/app/views/event_mailer/invitation_email.html.erb +63 -0
- data/app/views/events/_event_details.html.haml +54 -0
- data/app/views/events/_events_lis.html.haml +29 -0
- data/app/views/events/_invitation_text.html.erb +8 -0
- data/app/views/events/_pictures.html.haml +5 -0
- data/app/views/events/_public_index.html.haml +16 -0
- data/app/views/events/index.html.haml +24 -0
- data/app/views/events/show.html.haml +50 -0
- data/app/views/groups/_address_labels_modal.html.haml +27 -0
- data/app/views/groups/_export_button.html.haml +66 -0
- data/app/views/groups/_group_list.html.haml +25 -0
- data/app/views/groups/_member_avatars.html.haml +4 -0
- data/app/views/groups/_member_list.html.haml +15 -0
- data/app/views/groups/index.html.erb +11 -0
- data/app/views/groups/index_mine.html.haml +7 -0
- data/app/views/groups/show.html.haml +79 -0
- data/app/views/last_seen_activities/_index.html.haml +19 -0
- data/app/views/layouts/_add_structureable_additions.html.haml +15 -0
- data/app/views/layouts/_box.html.haml +16 -0
- data/app/views/layouts/_help_button.html.haml +1 -0
- data/app/views/layouts/_role_preview_switcher.html.haml +20 -0
- data/app/views/layouts/_session_bar_avatar.html.haml +1 -0
- data/app/views/layouts/_vertical_nav.html.haml +5 -0
- data/app/views/layouts/bootstrap.html.haml +146 -0
- data/app/views/layouts/mercury.html.erb +23 -0
- data/app/views/officers/_history_notice.html.haml +4 -0
- data/app/views/officers/_officers_box.html.haml +33 -0
- data/app/views/officers/_officers_group_entry.html.haml +45 -0
- data/app/views/pages/_attachments.html.haml +21 -0
- data/app/views/pages/_page.html.haml +28 -0
- data/app/views/pages/_pictures.html.haml +2 -0
- data/app/views/pages/_videos.html.erb +8 -0
- data/app/views/pages/show.html.haml +39 -0
- data/app/views/post_mailer/post_email.html.erb +17 -0
- data/app/views/posts/_new_post_template_text.html.haml +6 -0
- data/app/views/posts/_post.html.haml +13 -0
- data/app/views/posts/_post_quote.html.haml +18 -0
- data/app/views/posts/_posts.html.haml +6 -0
- data/app/views/posts/index.html.haml +9 -0
- data/app/views/posts/new.html.haml +42 -0
- data/app/views/posts/show.html.haml +8 -0
- data/app/views/profile_fields/_postal_address_flag_switch.html.haml +21 -0
- data/app/views/profile_fields/_profile_field.html.haml +41 -0
- data/app/views/profile_fields/create.js.erb +26 -0
- data/app/views/profile_fields/destroy.js.erb +3 -0
- data/app/views/profiles/_add_profile_field_button.html.haml +15 -0
- data/app/views/profiles/_profile_section_ul.html.haml +8 -0
- data/app/views/profiles/_section.html.haml +28 -0
- data/app/views/profiles/_send_group_message_button.html.haml +4 -0
- data/app/views/root/_latest_members_box.html.haml +19 -0
- data/app/views/root/_start_page_elements.html.haml +0 -0
- data/app/views/root/_what_is_new.html.haml +21 -0
- data/app/views/search/_preview_blog_post.html.haml +1 -0
- data/app/views/search/_preview_corporation.html.haml +5 -0
- data/app/views/search/_preview_group.html.haml +4 -0
- data/app/views/search/_preview_page.html.haml +11 -0
- data/app/views/search/_preview_user.html.haml +14 -0
- data/app/views/search/index.html.haml +42 -0
- data/app/views/setup/index.html.haml +56 -0
- data/app/views/shared/_add_structureable.html.haml +22 -0
- data/app/views/shared/_authorization_info.html.haml +22 -0
- data/app/views/shared/_flags.html.haml +5 -0
- data/app/views/shared/_markdown_help.html.haml +4 -0
- data/app/views/shared/_search_box.html.haml +2 -0
- data/app/views/shared/_upcoming_events.html.haml +33 -0
- data/app/views/statistics/index.html.haml +16 -0
- data/app/views/statistics/show.html.haml +13 -0
- data/app/views/terms_of_use/_checkbox.html.haml +1 -0
- data/app/views/terms_of_use/_terms.html.haml +1 -0
- data/app/views/terms_of_use/index.html.haml +19 -0
- data/app/views/user_account_mailer/welcome_email.html.erb +32 -0
- data/app/views/user_accounts/_change_password.html.haml +149 -0
- data/app/views/user_accounts/_user_account.html.haml +39 -0
- data/app/views/user_group_memberships/_list_item.html.haml +9 -0
- data/app/views/user_group_memberships/_memberships_table.html.haml +56 -0
- data/app/views/user_group_memberships/_new.html.haml +18 -0
- data/app/views/user_group_memberships/create.js.erb +9 -0
- data/app/views/user_group_memberships/index.html.haml +5 -0
- data/app/views/user_settings/show.html.haml +36 -0
- data/app/views/users/_avatar.html.haml +16 -0
- data/app/views/users/_communication_box.html.haml +8 -0
- data/app/views/users/_corporate_vita.html.haml +23 -0
- data/app/views/users/_dead_badge.html.haml +3 -0
- data/app/views/users/_deceased_modal.html.haml +24 -0
- data/app/views/users/_hidden_badge.html.haml +4 -0
- data/app/views/users/_hidden_flag_switch.html.haml +20 -0
- data/app/views/users/_special_general_info_fields.html.haml +10 -0
- data/app/views/users/_user_corporation_attribute.html.haml +6 -0
- data/app/views/users/_user_name_attribute.html.haml +4 -0
- data/app/views/users/_user_title.html.haml +5 -0
- data/app/views/users/_workflow_triggers.html.haml +23 -0
- data/app/views/users/new.html.haml +55 -0
- data/app/views/users/show.html.haml +79 -0
- data/config/environment.rb +5 -0
- data/config/initializers/active_record_cache_extension.rb +1 -0
- data/config/initializers/active_record_find_by_extension.rb +1 -0
- data/config/initializers/active_record_flagable_extension.rb +2 -0
- data/config/initializers/active_record_json_url_extension.rb +1 -0
- data/config/initializers/active_record_may_need_review_extension.rb +2 -0
- data/config/initializers/active_record_metric_events_extension.rb +1 -0
- data/config/initializers/active_record_navable_extension.rb +6 -0
- data/config/initializers/active_record_profileable_extension.rb +4 -0
- data/config/initializers/active_record_read_only_extension.rb +1 -0
- data/config/initializers/active_record_structureable_extension.rb +3 -0
- data/config/initializers/active_record_update_attributes_bip_extension.rb +1 -0
- data/config/initializers/array_extension.rb +1 -0
- data/config/initializers/best_in_place_display_definitions.rb +31 -0
- data/config/initializers/cache_store_extension.rb +1 -0
- data/config/initializers/devise.rb +240 -0
- data/config/initializers/fnordmetric.rb +14 -0
- data/config/initializers/formtastic.rb +76 -0
- data/config/initializers/group_type_column_patches.rb +11 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/initializers/mini_profiler.rb +32 -0
- data/config/initializers/object_to_b_extension.rb +1 -0
- data/config/initializers/refile.rb +22 -0
- data/config/initializers/sidekiq.rb +12 -0
- data/config/locales/attachments/de.yml +33 -0
- data/config/locales/bookmarks/de.yml +3 -0
- data/config/locales/bookmarks/en.yml +3 -0
- data/config/locales/common_expressions/de.yml +5 -0
- data/config/locales/common_expressions/en.yml +5 -0
- data/config/locales/companies/de.yml +4 -0
- data/config/locales/companies/en.yml +4 -0
- data/config/locales/de.yml +30 -0
- data/config/locales/devise/de.yml +60 -0
- data/config/locales/devise/en.yml +62 -0
- data/config/locales/en.yml +25 -0
- data/config/locales/events/de.yml +34 -0
- data/config/locales/events/en.yml +34 -0
- data/config/locales/forms/de.yml +3 -0
- data/config/locales/groups/de.yml +56 -0
- data/config/locales/groups/en.yml +47 -0
- data/config/locales/officers/de.yml +10 -0
- data/config/locales/pages/de.yml +15 -0
- data/config/locales/pages/en.yml +14 -0
- data/config/locales/pagination/de.yml +6 -0
- data/config/locales/pagination/en.yml +5 -0
- data/config/locales/password_strength/de.yml +9 -0
- data/config/locales/password_strength/en.yml +9 -0
- data/config/locales/posts/de.yml +9 -0
- data/config/locales/profile_fields/de.yml +78 -0
- data/config/locales/profile_fields/en.yml +22 -0
- data/config/locales/profiles/de.yml +47 -0
- data/config/locales/profiles/en.yml +44 -0
- data/config/locales/roles/de.yml +9 -0
- data/config/locales/root/de.yml +3 -0
- data/config/locales/root/en.yml +3 -0
- data/config/locales/search/de.yml +11 -0
- data/config/locales/search/en.yml +11 -0
- data/config/locales/sessions/de.yml +37 -0
- data/config/locales/sessions/en.yml +37 -0
- data/config/locales/setup/de.yml +26 -0
- data/config/locales/setup/en.yml +26 -0
- data/config/locales/statistics/de.yml +6 -0
- data/config/locales/terms_of_use/de.yml +6 -0
- data/config/locales/tools/de.yml +9 -0
- data/config/locales/tools/en.yml +9 -0
- data/config/locales/user_accounts/de.yml +16 -0
- data/config/locales/user_accounts/en.yml +13 -0
- data/config/locales/user_settings/de.yml +9 -0
- data/config/locales/users/de.yml +82 -0
- data/config/locales/users/en.yml +51 -0
- data/config/locales/workflows/de.yml +4 -0
- data/config/locales/workflows/en.yml +4 -0
- data/config/routes.rb +104 -0
- data/db/migrate/20120403002734_create_users.rb +12 -0
- data/db/migrate/20120403011601_create_profile_fields.rb +11 -0
- data/db/migrate/20120403161549_remove_user_email_column.rb +5 -0
- data/db/migrate/20120405222050_encrypt_password.rb +8 -0
- data/db/migrate/20120425161138_create_dag_links.rb +14 -0
- data/db/migrate/20120425162644_create_pages.rb +10 -0
- data/db/migrate/20120426023322_create_groups.rb +9 -0
- data/db/migrate/20120426090436_create_nav_nodes.rb +18 -0
- data/db/migrate/20120427021934_create_user_accounts.rb +12 -0
- data/db/migrate/20120427044338_add_foreign_key_to_user_accounts.rb +7 -0
- data/db/migrate/20120427150156_add_group_token.rb +8 -0
- data/db/migrate/20120507165551_make_profile_fields_polymorphic.rb +11 -0
- data/db/migrate/20120508130729_add_profile_field_acts_as_tree.rb +9 -0
- data/db/migrate/20120508152233_change_profile_field_value_to_text.rb +9 -0
- data/db/migrate/20120508201550_add_group_internal_token.rb +11 -0
- data/db/migrate/20120511090234_create_workflows.rb +9 -0
- data/db/migrate/20120701115059_add_password_digest_to_user_accounts.rb +5 -0
- data/db/migrate/20120710193308_remove_salt_from_user_accounts.rb +5 -0
- data/db/migrate/20120713102445_add_deleted_at_to_dag_links.rb +5 -0
- data/db/migrate/20120722005022_create_workflow_kit_workflows.workflow_kit.rb +11 -0
- data/db/migrate/20120722005023_create_workflow_kit_steps.workflow_kit.rb +12 -0
- data/db/migrate/20120722005024_create_workflow_kit_parameters.workflow_kit.rb +12 -0
- data/db/migrate/20120723165226_add_female_to_users.rb +5 -0
- data/db/migrate/20120811140509_create_flags.rb +11 -0
- data/db/migrate/20120814100529_create_attachments.rb +13 -0
- data/db/migrate/20120815205610_add_content_type_and_file_size_to_attachments.rb +6 -0
- data/db/migrate/20130118220014_add_relationships_table_without_dag.rb +10 -0
- data/db/migrate/20130207214331_create_events.rb +12 -0
- data/db/migrate/20130208215253_create_status_group_membership_infos.rb +11 -0
- data/db/migrate/20130220184943_create_stars.rb +11 -0
- data/db/migrate/20130309193623_add_devise_to_user_accounts.rb +72 -0
- data/db/migrate/20130310003840_rename_stars_to_bookmarks.rb +9 -0
- data/db/migrate/20130310004622_fix_column_names_for_bookmarks.rb +6 -0
- data/db/migrate/20130313211414_create_geo_infos.rb +13 -0
- data/db/migrate/20130313234131_create_geo_locations.rb +16 -0
- data/db/migrate/20130314011638_drop_geo_infos.rb +5 -0
- data/db/migrate/20130315072759_add_invalid_to_geo_location.rb +5 -0
- data/db/migrate/20130315073149_exchange_invalid_for_queried_at_in_geo_location.rb +8 -0
- data/db/migrate/20130320003051_add_redirect_to_to_page.rb +5 -0
- data/db/migrate/20130329231657_create_posts.rb +15 -0
- data/db/migrate/20130404223735_add_entire_message_to_posts.rb +5 -0
- data/db/migrate/20130409192959_add_author_to_page.rb +5 -0
- data/db/migrate/20130908011215_add_type_to_pages.rb +5 -0
- data/db/migrate/20131115114715_validity_range_for_dag_links.rb +16 -0
- data/db/migrate/20140611170430_create_activities.rb +23 -0
- data/db/migrate/20140808223512_create_last_seen_activities.rb +12 -0
- data/db/migrate/20141008101744_add_location_to_events.rb +5 -0
- data/db/migrate/20141010130344_add_publish_on_website_to_events.rb +6 -0
- data/db/migrate/20141010134227_add_auth_token_to_user_accounts.rb +5 -0
- data/db/migrate/20141018143323_add_accepted_terms_to_users.rb +6 -0
- data/db/migrate/20141018221659_add_author_to_attachments.rb +5 -0
- data/db/migrate/20141102223954_add_body_to_groups.rb +5 -0
- data/db/migrate/20141110193830_create_settings.rb +17 -0
- data/db/migrate/20141202140522_add_indices.rb +6 -0
- data/db/migrate/20141209161946_add_keys.rb +20 -0
- data/db/migrate/20150127013809_add_incognito_to_users.rb +5 -0
- data/db/migrate/20150129194501_add_indices_for_polymorphic_references.rb +13 -0
- data/db/migrate/20150304192448_add_type_to_groups.rb +5 -0
- data/db/migrate/20150313221004_add_avatar_id_to_users.rb +5 -0
- data/lib/best_in_place/controller_extensions.rb +25 -0
- data/lib/best_in_place/helper.rb +127 -0
- data/lib/tasks/db_bootstrap.rake +37 -0
- data/lib/tasks/your_platform_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +11 -0
- data/lib/your_platform.rb +6 -2
- data/lib/your_platform/engine.rb +127 -0
- data/lib/your_platform/version.rb +1 -1
- data/spec/factories/attachment.rb +12 -0
- data/spec/factories/blog_post.rb +10 -0
- data/spec/factories/company.rb +7 -0
- data/spec/factories/corporation.rb +20 -0
- data/spec/factories/event.rb +13 -0
- data/spec/factories/group.rb +36 -0
- data/spec/factories/html_email.eml +1059 -0
- data/spec/factories/mail_message.rb +30 -0
- data/spec/factories/page.rb +10 -0
- data/spec/factories/relationship.rb +13 -0
- data/spec/factories/status_group_membership.rb +21 -0
- data/spec/factories/user.rb +97 -0
- data/spec/factories/workflow.rb +44 -0
- data/spec/features/blog_post_spec.rb +46 -0
- data/spec/features/corporate_vita_events_spec.rb +114 -0
- data/spec/features/corporate_vita_spec.rb +258 -0
- data/spec/features/edit_mode_after_clicking_a_link_spec.rb +20 -0
- data/spec/features/events_spec.rb +356 -0
- data/spec/features/group_export_spec.rb +19 -0
- data/spec/features/group_post_spec.rb +89 -0
- data/spec/features/groups_of_groups_page_spec.rb +67 -0
- data/spec/features/groups_page_spec.rb +66 -0
- data/spec/features/groups_table_spec.rb +32 -0
- data/spec/features/help_page_spec.rb +22 -0
- data/spec/features/intranet_root_page_spec.rb +18 -0
- data/spec/features/locales_spec.rb +36 -0
- data/spec/features/maps_spec.rb +53 -0
- data/spec/features/mini_profiler_spec.rb +37 -0
- data/spec/features/officers_spec.rb +61 -0
- data/spec/features/page_redirects_spec.rb +23 -0
- data/spec/features/page_spec.rb +20 -0
- data/spec/features/postal_address_flag_spec.rb +46 -0
- data/spec/features/relationships_on_user_page_spec.rb +78 -0
- data/spec/features/review_membership_spec.rb +44 -0
- data/spec/features/search_field_spec.rb +121 -0
- data/spec/features/setup_spec.rb +63 -0
- data/spec/features/user_change_date_of_birth_spec.rb +26 -0
- data/spec/features/vertical_nav_spec.rb +27 -0
- data/spec/features/what_is_new_box_spec.rb +33 -0
- data/spec/helpers/attachments_helper_spec.rb +15 -0
- data/spec/models/ability_spec.rb +93 -0
- data/spec/models/active_record_cache_extension_spec.rb +177 -0
- data/spec/models/active_record_find_by_extension_spec.rb +26 -0
- data/spec/models/active_record_json_url_extension_spec.rb +79 -0
- data/spec/models/address_label_spec.rb +144 -0
- data/spec/models/app_version_spec.rb +38 -0
- data/spec/models/attachment_spec.rb +5 -0
- data/spec/models/bookmark_spec.rb +70 -0
- data/spec/models/concerns/user_corporations_spec.rb +71 -0
- data/spec/models/corporation_spec.rb +128 -0
- data/spec/models/dag_link_spec.rb +48 -0
- data/spec/models/event_spec.rb +267 -0
- data/spec/models/flag_spec.rb +20 -0
- data/spec/models/flagable_spec.rb +55 -0
- data/spec/models/geo_location_spec.rb +126 -0
- data/spec/models/group_mixins/corporations_spec.rb +95 -0
- data/spec/models/group_mixins/everyone_spec.rb +64 -0
- data/spec/models/group_mixins/guests_spec.rb +75 -0
- data/spec/models/group_mixins/hidden_users_spec.rb +21 -0
- data/spec/models/group_mixins/import_spec.rb +93 -0
- data/spec/models/group_mixins/memberships_spec.rb +303 -0
- data/spec/models/group_mixins/officers_spec.rb +63 -0
- data/spec/models/group_mixins/roles_spec.rb +46 -0
- data/spec/models/group_spec.rb +341 -0
- data/spec/models/list_export_spec.rb +155 -0
- data/spec/models/may_need_review_spec.rb +114 -0
- data/spec/models/nav_node_spec.rb +277 -0
- data/spec/models/navable_spec.rb +54 -0
- data/spec/models/page_spec.rb +185 -0
- data/spec/models/post_spec.rb +271 -0
- data/spec/models/profile_field_mixins/has_child_profile_fields_spec.rb +73 -0
- data/spec/models/profile_field_spec.rb +482 -0
- data/spec/models/profile_section_spec.rb +89 -0
- data/spec/models/profile_spec.rb +74 -0
- data/spec/models/profileable_mixins/adress_spec.rb +93 -0
- data/spec/models/profileable_spec.rb +152 -0
- data/spec/models/relationship_spec.rb +113 -0
- data/spec/models/status_group_membership_spec.rb +350 -0
- data/spec/models/status_group_spec.rb +103 -0
- data/spec/models/structureable_mixins/has_special_groups_spec.rb +479 -0
- data/spec/models/structureable_mixins/roles_spec.rb +517 -0
- data/spec/models/structureable_spec.rb +128 -0
- data/spec/models/user_account_spec.rb +142 -0
- data/spec/models/user_alias_spec.rb +57 -0
- data/spec/models/user_group_membership_mixins/validity_range_for_indirect_memberships_spec.rb +291 -0
- data/spec/models/user_group_membership_mixins/validity_range_spec.rb +293 -0
- data/spec/models/user_group_membership_spec.rb +428 -0
- data/spec/models/user_mixins/identification_spec.rb +27 -0
- data/spec/models/user_mixins/memberships_spec.rb +138 -0
- data/spec/models/user_spec.rb +1794 -0
- data/spec/old_yp_spec_helper.rb +46 -0
- data/spec/spec_helper.rb +350 -0
- data/spec/support/auto_complete.rb +22 -0
- data/spec/support/capybara/flash_helpers.rb +37 -0
- data/spec/support/capybara/profile_steps.rb +73 -0
- data/spec/support/capybara/session_steps.rb +53 -0
- data/spec/support/capybara/user_account_helpers.rb +15 -0
- data/spec/support/debug.rb +8 -0
- data/spec/support/devise-controller_macros.rb +15 -0
- data/spec/support/geocoder/stubs.rb +60 -0
- data/spec/support/press_enter.rb +15 -0
- data/spec/support/time_travel.rb +9 -0
- data/spec/support/uploads/image-upload.png +0 -0
- data/spec/support/uploads/pdf-upload.pdf +0 -0
- data/spec/support/wait_for_ajax.rb +39 -0
- data/spec/support/wait_for_cache.rb +7 -0
- data/spec/uploaders/attachment_uploader_spec.rb +47 -0
- data/vendor/assets/images/flags.png +0 -0
- data/vendor/assets/images/galleria/classic-loader.gif +0 -0
- data/vendor/assets/images/galleria/classic-map.png +0 -0
- data/vendor/assets/javascripts/best_in_place_datetime.js.coffee +45 -0
- data/vendor/assets/javascripts/galleria-classic.js +100 -0
- data/vendor/assets/javascripts/galleria.js +6919 -0
- data/vendor/assets/javascripts/gmaps4rails.js +2 -0
- data/vendor/assets/javascripts/gmaps4rails/all.js +1 -0
- data/vendor/assets/javascripts/gmaps4rails/base.coffee +1 -0
- data/vendor/assets/javascripts/gmaps4rails/base/common.coffee +43 -0
- data/vendor/assets/javascripts/gmaps4rails/base/configuration.coffee +7 -0
- data/vendor/assets/javascripts/gmaps4rails/base/gmaps.coffee +13 -0
- data/vendor/assets/javascripts/gmaps4rails/base/interfaces/basic_interface.coffee +15 -0
- data/vendor/assets/javascripts/gmaps4rails/base/interfaces/controller_interface.coffee +15 -0
- data/vendor/assets/javascripts/gmaps4rails/base/interfaces/map_interface.coffee +27 -0
- data/vendor/assets/javascripts/gmaps4rails/base/interfaces/marker_interface.coffee +15 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main.coffee +124 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/circle_controller.coffee +29 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/kml_controller.coffee +5 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/marker_controller.coffee +76 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/polygon_controller.coffee +29 -0
- data/vendor/assets/javascripts/gmaps4rails/base/main_controller_extensions/polyline_controller.coffee +29 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/circle.coffee +12 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/kml.coffee +8 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/map.coffee +62 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/marker.coffee +24 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/polygon.coffee +11 -0
- data/vendor/assets/javascripts/gmaps4rails/base/objects/polyline.coffee +11 -0
- data/vendor/assets/javascripts/gmaps4rails/bing.coffee +1 -0
- data/vendor/assets/javascripts/gmaps4rails/bing/main.coffee +29 -0
- data/vendor/assets/javascripts/gmaps4rails/bing/objects/map.coffee +63 -0
- data/vendor/assets/javascripts/gmaps4rails/bing/objects/marker.coffee +78 -0
- data/vendor/assets/javascripts/gmaps4rails/bing/shared.coffee +20 -0
- data/vendor/assets/javascripts/gmaps4rails/google.coffee +1 -0
- data/vendor/assets/javascripts/gmaps4rails/google/main.coffee +47 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/circle.coffee +38 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/kml.coffee +16 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/map.coffee +71 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/marker.coffee +114 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/polygon.coffee +38 -0
- data/vendor/assets/javascripts/gmaps4rails/google/objects/polyline.coffee +49 -0
- data/vendor/assets/javascripts/gmaps4rails/google/shared.coffee +27 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers.coffee +1 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers/main.coffee +138 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/map.coffee +49 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/marker.coffee +68 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers/objects/polyline.coffee +39 -0
- data/vendor/assets/javascripts/gmaps4rails/openlayers/shared.coffee +19 -0
- data/vendor/assets/javascripts/jquery-ui-timepicker-addon.js +2223 -0
- data/vendor/assets/javascripts/jquery-ui-timepicker-de.js +26 -0
- data/vendor/assets/javascripts/jquery.ui.datepicker-de.js +23 -0
- data/vendor/assets/javascripts/password_strength.js +149 -0
- data/vendor/assets/javascripts/zxcvbn.js +43 -0
- data/vendor/assets/stylesheets/flags.css.scss +259 -0
- data/vendor/assets/stylesheets/galleria-classic.css.scss +239 -0
- data/vendor/assets/stylesheets/gmaps4rails.css +24 -0
- data/vendor/assets/stylesheets/mercury.css +24 -0
- data/vendor/scripts/bashpass/README.md +29 -0
- data/vendor/scripts/bashpass/bashpass +124 -0
- data/vendor/scripts/bashpass/bashpass-APACHE-LICENSE +201 -0
- data/vendor/scripts/bashpass/german.dic +40794 -0
- metadata +1540 -16
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -4
- 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
|
data/app/models/user.rb
ADDED
|
@@ -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
|
+
|