diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 09331bb03f010231f7e6d9a5b3710b94bc2b0c2a..a0c0abf13b4e296af07e2df727442244ca5550c2 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -117,19 +117,34 @@ module IssuableCollections key = 'issuable_sort' cookies[key] = params[:sort] if params[:sort].present? - - # id_desc and id_asc are old values for these two. - cookies[key] = sort_value_recently_created if cookies[key] == 'id_desc' - cookies[key] = sort_value_oldest_created if cookies[key] == 'id_asc' - + cookies[key] = update_cookie_value(cookies[key]) params[:sort] = cookies[key] end def default_sort_order case params[:state] - when 'opened', 'all' then sort_value_recently_created + when 'opened', 'all' then sort_value_created_date when 'merged', 'closed' then sort_value_recently_updated - else sort_value_recently_created + else sort_value_created_date + end + end + + # Update old values to the actual ones. + def update_cookie_value(value) + case value + when 'id_asc' then sort_value_oldest_created + when 'id_desc' then sort_value_recently_created + when 'created_asc' then sort_value_created_date + when 'created_desc' then sort_value_created_date + when 'due_date_asc' then sort_value_due_date + when 'due_date_desc' then sort_value_due_date + when 'milestone_due_asc' then sort_value_milestone + when 'milestone_due_desc' then sort_value_milestone + when 'downvotes_asc' then sort_value_popularity + when 'downvotes_desc' then sort_value_popularity + when 'weight_asc' then sort_value_weight + when 'weight_desc' then sort_value_weight + else value end end end diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 1066b764f4f02a459c5a948de82463b3995b2942..d01df740808dfbc27252936ad96c9d798c685c12 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -1,36 +1,41 @@ module SortingHelper def sort_options_hash { - sort_value_name => sort_title_name, - sort_value_name_desc => sort_title_name_desc, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_created_date => sort_title_created_date, + sort_value_downvotes => sort_title_downvotes, + sort_value_due_date => sort_title_due_date, + sort_value_due_date_later => sort_title_due_date_later, + sort_value_due_date_soon => sort_title_due_date_soon, + sort_value_label_priority => sort_title_label_priority, + sort_value_largest_group => sort_title_largest_group, + sort_value_largest_repo => sort_title_largest_repo, + sort_value_milestone => sort_title_milestone, + sort_value_milestone_later => sort_title_milestone_later, + sort_value_milestone_soon => sort_title_milestone_soon, + sort_value_less_weight => sort_title_less_weight, + sort_value_more_weight => sort_title_more_weight, + sort_value_name => sort_title_name, + sort_value_name_desc => sort_title_name_desc, + sort_value_oldest_created => sort_title_oldest_created, + sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_oldest_updated => sort_title_oldest_updated, sort_value_recently_created => sort_title_recently_created, - sort_value_oldest_created => sort_title_oldest_created, - sort_value_milestone_soon => sort_title_milestone_soon, - sort_value_milestone_later => sort_title_milestone_later, - sort_value_due_date_soon => sort_title_due_date_soon, - sort_value_due_date_later => sort_title_due_date_later, - sort_value_largest_repo => sort_title_largest_repo, - sort_value_largest_group => sort_title_largest_group, - sort_value_recently_signin => sort_title_recently_signin, - sort_value_oldest_signin => sort_title_oldest_signin, - sort_value_downvotes => sort_title_downvotes, - sort_value_upvotes => sort_title_upvotes, - sort_value_more_weight => sort_title_more_weight, - sort_value_less_weight => sort_title_less_weight, - sort_value_priority => sort_title_priority, - sort_value_label_priority => sort_title_label_priority + sort_value_recently_signin => sort_title_recently_signin, + sort_value_recently_updated => sort_title_recently_updated, + sort_value_popularity => sort_title_popularity, + sort_value_priority => sort_title_priority, + sort_value_upvotes => sort_title_upvotes, + sort_value_weight => sort_title_weight } end def projects_sort_options_hash options = { - sort_value_name => sort_title_name, - sort_value_latest_activity => sort_title_latest_activity, - sort_value_oldest_activity => sort_title_oldest_activity, - sort_value_recently_created => sort_title_recently_created, - sort_value_oldest_created => sort_title_oldest_created + sort_value_latest_activity => sort_title_latest_activity, + sort_value_name => sort_title_name, + sort_value_oldest_activity => sort_title_oldest_activity, + sort_value_oldest_created => sort_title_oldest_created, + sort_value_recently_created => sort_title_recently_created } if current_controller?('admin/projects') @@ -42,168 +47,186 @@ module SortingHelper def member_sort_options_hash { - sort_value_access_level_asc => sort_title_access_level_asc, + sort_value_access_level_asc => sort_title_access_level_asc, sort_value_access_level_desc => sort_title_access_level_desc, - sort_value_last_joined => sort_title_last_joined, - sort_value_oldest_joined => sort_title_oldest_joined, - sort_value_name => sort_title_name_asc, - sort_value_name_desc => sort_title_name_desc, - sort_value_recently_signin => sort_title_recently_signin, - sort_value_oldest_signin => sort_title_oldest_signin + sort_value_last_joined => sort_title_last_joined, + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc, + sort_value_oldest_joined => sort_title_oldest_joined, + sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_recently_signin => sort_title_recently_signin } end def milestone_sort_options_hash { - sort_value_name => sort_title_name_asc, - sort_value_name_desc => sort_title_name_desc, - sort_value_due_date_soon => sort_title_due_date_soon, - sort_value_due_date_later => sort_title_due_date_later, - sort_value_start_date_soon => sort_title_start_date_soon, - sort_value_start_date_later => sort_title_start_date_later + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc, + sort_value_due_date_later => sort_title_due_date_later, + sort_value_due_date_soon => sort_title_due_date_soon, + sort_value_start_date_later => sort_title_start_date_later, + sort_value_start_date_soon => sort_title_start_date_soon } end def branches_sort_options_hash { - sort_value_name => sort_title_name, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated + sort_value_name => sort_title_name, + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_updated => sort_title_recently_updated } end def tags_sort_options_hash { - sort_value_name => sort_title_name, - sort_value_recently_updated => sort_title_recently_updated, - sort_value_oldest_updated => sort_title_oldest_updated + sort_value_name => sort_title_name, + sort_value_oldest_updated => sort_title_oldest_updated, + sort_value_recently_updated => sort_title_recently_updated } end - def sort_title_priority - s_('SortOptions|Priority') + def sortable_item(item, path, sorted_by) + link_to item, path, class: sorted_by == item ? 'is-active' : '' end - def sort_title_label_priority - s_('SortOptions|Label priority') + # Titles. + def sort_title_access_level_asc + s_('SortOptions|Access level, ascending') end - def sort_title_oldest_updated - s_('SortOptions|Oldest updated') + def sort_title_access_level_desc + s_('SortOptions|Access level, descending') end - def sort_title_recently_updated - s_('SortOptions|Last updated') + def sort_title_created_date + s_('SortOptions|Created date') end - def sort_title_oldest_activity - s_('SortOptions|Oldest updated') + def sort_title_downvotes + s_('SortOptions|Least popular') end - def sort_title_latest_activity - s_('SortOptions|Last updated') + def sort_title_due_date + s_('SortOptions|Due date') end - def sort_title_oldest_created - s_('SortOptions|Oldest created') + def sort_title_due_date_later + s_('SortOptions|Due later') end - def sort_title_recently_created - s_('SortOptions|Last created') + def sort_title_due_date_soon + s_('SortOptions|Due soon') end - def sort_title_milestone_soon - s_('SortOptions|Milestone due soon') + def sort_title_label_priority + s_('SortOptions|Label priority') end - def sort_title_milestone_later - s_('SortOptions|Milestone due later') + def sort_title_largest_group + s_('SortOptions|Largest group') end - def sort_title_due_date_soon - s_('SortOptions|Due soon') + def sort_title_largest_repo + s_('SortOptions|Largest repository') end - def sort_title_due_date_later - s_('SortOptions|Due later') + def sort_title_last_joined + s_('SortOptions|Last joined') end - def sort_title_start_date_soon - s_('SortOptions|Start soon') + def sort_title_latest_activity + s_('SortOptions|Last updated') end - def sort_title_start_date_later - s_('SortOptions|Start later') + def sort_title_less_weight + s_('SortOptions|Less weight') + end + + def sort_title_milestone + s_('SortOptions|Milestone') + end + + def sort_title_milestone_later + s_('SortOptions|Milestone due later') + end + + def sort_title_milestone_soon + s_('SortOptions|Milestone due soon') + end + + def sort_title_more_weight + s_('SortOptions|More weight') end def sort_title_name s_('SortOptions|Name') end - def sort_title_largest_repo - s_('SortOptions|Largest repository') + def sort_title_name_asc + s_('SortOptions|Name, ascending') end - def sort_title_largest_group - s_('SortOptions|Largest group') + def sort_title_name_desc + s_('SortOptions|Name, descending') end - def sort_title_recently_signin - s_('SortOptions|Recent sign in') + def sort_title_oldest_activity + s_('SortOptions|Oldest updated') end - def sort_title_oldest_signin - s_('SortOptions|Oldest sign in') + def sort_title_oldest_created + s_('SortOptions|Oldest created') end - def sort_title_downvotes - s_('SortOptions|Least popular') + def sort_title_oldest_joined + s_('SortOptions|Oldest joined') end - def sort_title_upvotes - s_('SortOptions|Most popular') + def sort_title_oldest_signin + s_('SortOptions|Oldest sign in') end - def sort_title_more_weight - 'More weight' + def sort_title_oldest_updated + s_('SortOptions|Oldest updated') end - def sort_title_less_weight - 'Less weight' + def sort_title_popularity + s_('SortOptions|Popularity') end - def sort_title_last_joined - s_('SortOptions|Last joined') + def sort_title_priority + s_('SortOptions|Priority') end - def sort_title_oldest_joined - s_('SortOptions|Oldest joined') + def sort_title_recently_created + s_('SortOptions|Last created') end - def sort_title_access_level_asc - s_('SortOptions|Access level, ascending') + def sort_title_recently_signin + s_('SortOptions|Recent sign in') end - def sort_title_access_level_desc - s_('SortOptions|Access level, descending') + def sort_title_recently_updated + s_('SortOptions|Last updated') end - def sort_title_name_asc - s_('SortOptions|Name, ascending') + def sort_title_start_date_later + s_('SortOptions|Start later') end - def sort_title_name_desc - s_('SortOptions|Name, descending') + def sort_title_start_date_soon + s_('SortOptions|Start soon') end - def sort_value_last_joined - 'last_joined' + def sort_title_upvotes + s_('SortOptions|Most popular') end - def sort_value_oldest_joined - 'oldest_joined' + def sort_title_weight + s_('SortOptions|Weight') end + # Values. def sort_value_access_level_asc 'access_level_asc' end @@ -212,99 +235,127 @@ module SortingHelper 'access_level_desc' end - def sort_value_name_desc - 'name_desc' + def sort_value_created_date + 'created_date' end - def sort_value_priority - 'priority' + def sort_value_downvotes + 'downvotes_desc' + end + + def sort_value_due_date + 'due_date' + end + + def sort_value_due_date_later + 'due_date_desc' + end + + def sort_value_due_date_soon + 'due_date_asc' end def sort_value_label_priority 'label_priority' end - def sort_value_oldest_updated - 'updated_asc' + def sort_value_largest_group + 'storage_size_desc' end - def sort_value_recently_updated - 'updated_desc' + def sort_value_largest_repo + 'storage_size_desc' end - def sort_value_oldest_activity - 'latest_activity_asc' + def sort_value_last_joined + 'last_joined' end def sort_value_latest_activity 'latest_activity_desc' end - def sort_value_oldest_created - 'created_asc' + def sort_value_less_weight + 'weight_asc' end - def sort_value_recently_created - 'created_desc' + def sort_value_milestone + 'milestone' + end + + def sort_value_milestone_later + 'milestone_due_desc' end def sort_value_milestone_soon 'milestone_due_asc' end - def sort_value_milestone_later - 'milestone_due_desc' + def sort_value_more_weight + 'weight_desc' end - def sort_value_due_date_soon - 'due_date_asc' + def sort_value_name + 'name_asc' end - def sort_value_due_date_later - 'due_date_desc' + def sort_value_name_desc + 'name_desc' end - def sort_value_start_date_soon - 'start_date_asc' + def sort_value_oldest_activity + 'latest_activity_asc' end - def sort_value_start_date_later - 'start_date_desc' + def sort_value_oldest_created + 'created_asc' end - def sort_value_name - 'name_asc' + def sort_value_oldest_signin + 'oldest_sign_in' end - def sort_value_largest_repo - 'storage_size_desc' + def sort_value_oldest_joined + 'oldest_joined' end - def sort_value_largest_group - 'storage_size_desc' + def sort_value_oldest_updated + 'updated_asc' + end + + def sort_value_popularity + 'popularity' + end + + def sort_value_priority + 'priority' + end + + def sort_value_recently_created + 'created_desc' end def sort_value_recently_signin 'recent_sign_in' end - def sort_value_oldest_signin - 'oldest_sign_in' + def sort_value_recently_updated + 'updated_desc' end - def sort_value_downvotes - 'downvotes_desc' + def sort_value_start_date_later + 'start_date_desc' end - def sort_value_upvotes - 'upvotes_desc' + def sort_value_start_date_soon + 'start_date_asc' end - def sort_value_more_weight - 'weight_desc' + def sort_value_upvotes + 'upvotes_desc' end - def sort_value_less_weight - 'weight_asc' + def sort_value_weight + 'weight' end end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index b79e7465350d02ee4a5ad84fba98e8743d393891..cb2f58ed0709c0362dec61589b8fa789bf6bc896 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -142,16 +142,18 @@ module Issuable end def sort(method, excluded_labels: []) - sorted = case method.to_s - when 'milestone_due_asc' then order_milestone_due_asc - when 'milestone_due_desc' then order_milestone_due_desc - when 'downvotes_desc' then order_downvotes_desc - when 'upvotes_desc' then order_upvotes_desc - when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels) - when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels) - else - order_by(method) - end + sorted = + case method.to_s + when 'downvotes_desc' then order_downvotes_desc + when 'label_priority' then order_labels_priority(excluded_labels: excluded_labels) + when 'milestone' then order_milestone_due_asc + when 'milestone_due_asc' then order_milestone_due_asc + when 'milestone_due_desc' then order_milestone_due_desc + when 'popularity' then order_upvotes_desc + when 'priority' then order_due_date_and_labels_priority(excluded_labels: excluded_labels) + when 'upvotes_desc' then order_upvotes_desc + else order_by(method) + end # Break ties with the ID column for pagination sorted.order(id: :desc) @@ -224,7 +226,7 @@ module Issuable def grouping_columns(sort) grouping_columns = [arel_table[:id]] - if %w(milestone_due_desc milestone_due_asc).include?(sort) + if %w(milestone_due_desc milestone_due_asc milestone).include?(sort) milestone_table = Milestone.arel_table grouping_columns << milestone_table[:id] grouping_columns << milestone_table[:due_date] diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb index db3cd25758411fab237e97c9005bd67cf275e700..cefa5c13c5ff845c2a186423b7729f96082254c7 100644 --- a/app/models/concerns/sortable.rb +++ b/app/models/concerns/sortable.rb @@ -19,14 +19,15 @@ module Sortable module ClassMethods def order_by(method) case method.to_s - when 'name_asc' then order_name_asc - when 'name_desc' then order_name_desc - when 'updated_asc' then order_updated_asc - when 'updated_desc' then order_updated_desc - when 'created_asc' then order_created_asc + when 'created_asc' then order_created_asc + when 'created_date' then order_created_desc when 'created_desc' then order_created_desc - when 'id_desc' then order_id_desc - when 'id_asc' then order_id_asc + when 'id_asc' then order_id_asc + when 'id_desc' then order_id_desc + when 'name_asc' then order_name_asc + when 'name_desc' then order_name_desc + when 'updated_asc' then order_updated_asc + when 'updated_desc' then order_updated_desc else all end diff --git a/app/models/issue.rb b/app/models/issue.rb index 6c3cd8c0703d98e02410cb964b378fc80357c4e5..fcb44766420d5d12d46f876f27139494b3e8d9d8 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -128,10 +128,12 @@ class Issue < ActiveRecord::Base def self.sort(method, excluded_labels: []) case method.to_s - when 'due_date_asc' then order_due_date_asc + when 'due_date' then order_due_date_asc + when 'due_date_asc' then order_due_date_asc when 'due_date_desc' then order_due_date_desc - when 'weight_desc' then order_weight_desc - when 'weight_asc' then order_weight_asc + when 'weight' then order_weight_asc + when 'weight_asc' then order_weight_asc + when 'weight_desc' then order_weight_desc else super end diff --git a/app/services/geo/node_status_service.rb b/app/services/geo/node_status_service.rb index 36ad627e6b1ddc8c6fa1fab182e260e474077824..0c68e5e27148ff57ee65288f0d682ebf36fd81fa 100644 --- a/app/services/geo/node_status_service.rb +++ b/app/services/geo/node_status_service.rb @@ -41,7 +41,7 @@ module Geo end rescue OpenSSL::Cipher::CipherError ['Error decrypting the Geo secret from the database. Check that the primary uses the correct db_key_base.'] - rescue HTTParty::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => e + rescue HTTParty::Error, Timeout::Error, SocketError, SystemCallError, OpenSSL::SSL::SSLError => e [e.message] end diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index 1d28b7fb68ac14f7cf99b49fac6d8a70ef29b1d6..d8ca294326e3ad13eb63130eea22771a45141412 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -1,43 +1,20 @@ +- sorted_by = sort_options_hash[@sort] - viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues' .dropdown.inline.prepend-left-10 - %button.dropdown-toggle{ type: 'button', data: {toggle: 'dropdown' } } - - if @sort.present? - = sort_options_hash[@sort] - - else - = sort_title_recently_created + %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } } + = sorted_by = icon('chevron-down') - %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable.dropdown-menu-sort %li - = link_to page_filter_path(sort: sort_value_priority, label: true) do - = sort_title_priority - = link_to page_filter_path(sort: sort_value_label_priority, label: true) do - = sort_title_label_priority - = link_to page_filter_path(sort: sort_value_recently_created, label: true) do - = sort_title_recently_created - = link_to page_filter_path(sort: sort_value_oldest_created, label: true) do - = sort_title_oldest_created - = link_to page_filter_path(sort: sort_value_recently_updated, label: true) do - = sort_title_recently_updated - = link_to page_filter_path(sort: sort_value_oldest_updated, label: true) do - = sort_title_oldest_updated + = sortable_item(sort_title_priority, page_filter_path(sort: sort_value_priority, label: true), sorted_by) + = sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_created_date, label: true), sorted_by) + = sortable_item(sort_title_recently_updated, page_filter_path(sort: sort_value_recently_updated, label: true), sorted_by) - if viewing_issues && (@project || @group)&.feature_available?(:issue_weights) - = link_to page_filter_path(sort: sort_value_more_weight, label: true) do - = sort_title_more_weight - = link_to page_filter_path(sort: sort_value_less_weight, label: true) do - = sort_title_less_weight + = sortable_item(sort_title_weight, page_filter_path(sort: sort_value_weight, label: true), sorted_by) - = link_to page_filter_path(sort: sort_value_milestone_soon, label: true) do - = sort_title_milestone_soon - = link_to page_filter_path(sort: sort_value_milestone_later, label: true) do - = sort_title_milestone_later - - if viewing_issues - = link_to page_filter_path(sort: sort_value_due_date_soon, label: true) do - = sort_title_due_date_soon - = link_to page_filter_path(sort: sort_value_due_date_later, label: true) do - = sort_title_due_date_later - = link_to page_filter_path(sort: sort_value_upvotes, label: true) do - = sort_title_upvotes - = link_to page_filter_path(sort: sort_value_downvotes, label: true) do - = sort_title_downvotes + = sortable_item(sort_title_milestone, page_filter_path(sort: sort_value_milestone, label: true), sorted_by) + = sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date, label: true), sorted_by) if viewing_issues + = sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity, label: true), sorted_by) + = sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority, label: true), sorted_by) diff --git a/changelogs/unreleased-ee/3516-fix-nomethoderror-zero-on-nil.yml b/changelogs/unreleased-ee/3516-fix-nomethoderror-zero-on-nil.yml new file mode 100644 index 0000000000000000000000000000000000000000..cc1cc7bf11925328341b71e99ebecbc64eb74e6f --- /dev/null +++ b/changelogs/unreleased-ee/3516-fix-nomethoderror-zero-on-nil.yml @@ -0,0 +1,5 @@ +--- +title: Fix an error reporting some failures in the elasticsearch indexer +merge_request: 2998 +author: +type: fixed diff --git a/changelogs/unreleased/improve_sorting_list.yml b/changelogs/unreleased/improve_sorting_list.yml new file mode 100644 index 0000000000000000000000000000000000000000..a3730e23ed19fbf52a35ebb258ac1cda6e91f5b5 --- /dev/null +++ b/changelogs/unreleased/improve_sorting_list.yml @@ -0,0 +1,5 @@ +--- +title: Improve list of sorting options +merge_request: 14320 +author: Vitaliy @blackst0ne Klachkov +type: added diff --git a/doc/administration/high_availability/alpha_database.md b/doc/administration/high_availability/alpha_database.md index 1da8c69b4abecad8b43062cc9ce89bf9be6d8254..d0c5e045add2a2c42222261db07dc9da311700a3 100644 --- a/doc/administration/high_availability/alpha_database.md +++ b/doc/administration/high_availability/alpha_database.md @@ -262,7 +262,7 @@ get the cluster up and running. Verify the nodes are all communicating: ```sh -sudo consul members +sudo /opt/gitlab/embedded/bin/consul members ``` The output should be similar to: diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index 4f905674d8ccab98e7dfbc9c2646a0aa7ce445bc..d6cfa524a3a656da9180df526909953a2a46c5ce 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -51,36 +51,34 @@ Feature: Project Issues @javascript Scenario: Visiting Issues after being sorted the list Given I visit project "Shop" issues page - And I sort the list by "Oldest updated" + And I sort the list by "Last updated" And I visit my project's home page And I visit project "Shop" issues page - Then The list should be sorted by "Oldest updated" + Then The list should be sorted by "Last updated" @javascript Scenario: Visiting Merge Requests after being sorted the list Given project "Shop" has a "Bugfix MR" merge request open And I visit project "Shop" issues page - And I sort the list by "Oldest updated" + And I sort the list by "Last updated" And I visit project "Shop" merge requests page - Then The list should be sorted by "Oldest updated" + Then The list should be sorted by "Last updated" @javascript Scenario: Visiting Merge Requests from a differente Project after sorting Given project "Shop" has a "Bugfix MR" merge request open And I visit project "Shop" merge requests page - And I sort the list by "Oldest updated" + And I sort the list by "Last updated" And I visit dashboard merge requests page - Then The list should be sorted by "Oldest updated" + Then The list should be sorted by "Last updated" @javascript Scenario: Sort issues by upvotes/downvotes Given project "Shop" have "Bugfix" open issue And issue "Release 0.4" have 2 upvotes and 1 downvote And issue "Tweet control" have 1 upvote and 2 downvotes - And I sort the list by "Most popular" - Then The list should be sorted by "Most popular" - And I sort the list by "Least popular" - Then The list should be sorted by "Least popular" + And I sort the list by "Popularity" + Then The list should be sorted by "Popularity" # Markdown diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index 5873a5480403a6713465b29dc31c39f9b4fc8000..4b4cba68edbcf2fba71346d5ae0c3149c5fc524e 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -91,28 +91,26 @@ Feature: Project Merge Requests @javascript Scenario: Visiting Merge Requests after being sorted the list Given I visit project "Shop" merge requests page - And I sort the list by "Oldest updated" + And I sort the list by "Last updated" And I visit my project's home page And I visit project "Shop" merge requests page - Then The list should be sorted by "Oldest updated" + Then The list should be sorted by "Last updated" @javascript Scenario: Visiting Merge Requests from a different Project after sorting Given I visit project "Shop" merge requests page - And I sort the list by "Oldest updated" + And I sort the list by "Last updated" And I visit dashboard merge requests page - Then The list should be sorted by "Oldest updated" + Then The list should be sorted by "Last updated" @javascript - Scenario: Sort merge requests by upvotes/downvotes + Scenario: Sort merge requests by upvotes Given project "Shop" have "Bug NS-05" open merge request with diffs inside And project "Shop" have "Bug NS-06" open merge request And merge request "Bug NS-04" have 2 upvotes and 1 downvote And merge request "Bug NS-06" have 1 upvote and 2 downvotes - And I sort the list by "Most popular" - Then The list should be sorted by "Most popular" - And I sort the list by "Least popular" - Then The list should be sorted by "Least popular" + And I sort the list by "Popularity" + Then The list should be sorted by "Popularity" @javascript Scenario: I comment on a merge request diff diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index b9460f5b53456b142ee61b144b8300eb561a1c8d..2c3ef2efd52d880937af49065189cae6bf47dbfd 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -223,7 +223,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps end end - step 'The list should be sorted by "Most popular"' do + step 'The list should be sorted by "Popularity"' do page.within '.issues-list' do page.within 'li.issue:nth-child(1)' do expect(page).to have_content 'Release 0.4' diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index f0ef37ced192a2160aa4a1813e14ae6ac5d3521c..e24f93b5ffbc20473754b60780314b4cb994dbb1 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -222,7 +222,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end end - step 'The list should be sorted by "Most popular"' do + step 'The list should be sorted by "Popularity"' do page.within '.mr-list' do page.within 'li.merge-request:nth-child(1)' do expect(page).to have_content 'Bug NS-04' diff --git a/features/steps/shared/issuable.rb b/features/steps/shared/issuable.rb index 1d382d6320bc6150bea1720b6ef6e2987db6046a..37aeb760773fa1cccff99873b139b91b53607cc1 100644 --- a/features/steps/shared/issuable.rb +++ b/features/steps/shared/issuable.rb @@ -112,10 +112,10 @@ module SharedIssuable edit_issuable end - step 'I sort the list by "Oldest updated"' do + step 'I sort the list by "Last updated"' do find('button.dropdown-toggle').click page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do - click_link "Oldest updated" + click_link "Last updated" end end @@ -127,16 +127,16 @@ module SharedIssuable end end - step 'I sort the list by "Most popular"' do + step 'I sort the list by "Popularity"' do find('button.dropdown-toggle').click page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do - click_link 'Most popular' + click_link 'Popularity' end end - step 'The list should be sorted by "Oldest updated"' do - expect(find('.issues-filters')).to have_content('Oldest updated') + step 'The list should be sorted by "Last updated"' do + expect(find('.issues-filters')).to have_content('Last updated') end step 'I click link "Next" in the sidebar' do diff --git a/lib/gitlab/elastic/indexer.rb b/lib/gitlab/elastic/indexer.rb index 08579da117dcaf369dbd9fe40ade84ca24691138..9cf0793f29fc7855dd62fcddee50d840a0668a0c 100644 --- a/lib/gitlab/elastic/indexer.rb +++ b/lib/gitlab/elastic/indexer.rb @@ -63,7 +63,7 @@ module Gitlab output, status = Gitlab::Popen.popen(command, nil, vars) - raise Error, output unless status.zero? + raise Error, output unless status&.zero? end def update_index_status(to_sha) diff --git a/spec/ee/spec/controllers/projects/issues_controller_spec.rb b/spec/ee/spec/controllers/projects/issues_controller_spec.rb index bd98b369e22b205412753ff83c20f2416adbd041..446b5d68902fc1218615253d93a892abe13ba9cb 100644 --- a/spec/ee/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/ee/spec/controllers/projects/issues_controller_spec.rb @@ -100,19 +100,10 @@ describe Projects::IssuesController do end describe '#index' do - it 'allows sorting by weight (ascending)' do + it 'allows sorting by weight' do expected = [issue, issue2].sort_by(&:weight) - perform :get, :index, sort: 'weight_asc' - - expect(response).to have_http_status(200) - expect(assigns(:issues)).to eq(expected) - end - - it 'allows sorting by weight (descending)' do - expected = [issue, issue2].sort { |a, b| b.weight <=> a.weight } - - perform :get, :index, sort: 'weight_desc' + perform :get, :index, sort: 'weight' expect(response).to have_http_status(200) expect(assigns(:issues)).to eq(expected) @@ -157,9 +148,6 @@ describe Projects::IssuesController do end describe '#index' do - it 'ignores sorting by weight (ascending)' - it 'ignores sorting by weight (descending)' - it 'ignores filtering by weight' do expected = [issue, issue2] diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb index facb67ae78757e7394724fbc02232767b6163998..8759950e013e976dbe94df41d594936a8da652fa 100644 --- a/spec/features/dashboard/issues_filter_spec.rb +++ b/spec/features/dashboard/issues_filter_spec.rb @@ -90,17 +90,17 @@ feature 'Dashboard Issues filtering', :js do context 'sorting' do it 'shows sorted issues' do - sorting_by('Oldest updated') + sorting_by('Created date') visit_issues - expect(find('.issues-filters')).to have_content('Oldest updated') + expect(find('.issues-filters')).to have_content('Created date') end it 'keeps sorting issues after visiting Projects Issues page' do - sorting_by('Oldest updated') + sorting_by('Created date') visit project_issues_path(project) - expect(find('.issues-filters')).to have_content('Oldest updated') + expect(find('.issues-filters')).to have_content('Created date') end end diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb index b4992dd54a16bb4784d17bcd3fe2fcde205e1a0a..8204828b5b96ef11d75d2ebc8d181b4b3137d181 100644 --- a/spec/features/dashboard/merge_requests_spec.rb +++ b/spec/features/dashboard/merge_requests_spec.rb @@ -112,19 +112,19 @@ feature 'Dashboard Merge Requests' do end it 'shows sorted merge requests' do - sorting_by('Oldest updated') + sorting_by('Created date') visit merge_requests_dashboard_path(assignee_id: current_user.id) - expect(find('.issues-filters')).to have_content('Oldest updated') + expect(find('.issues-filters')).to have_content('Created date') end it 'keeps sorting merge requests after visiting Projects MR page' do - sorting_by('Oldest updated') + sorting_by('Created date') visit project_merge_requests_path(project) - expect(find('.issues-filters')).to have_content('Oldest updated') + expect(find('.issues-filters')).to have_content('Created date') end end end diff --git a/spec/features/issuables/default_sort_order_spec.rb b/spec/features/issuables/default_sort_order_spec.rb index b72b690110fc4bed1d1dd4b601dd7008a3e41507..925d026ed611f2fc4d34e581b0d26bdbfcc482a2 100644 --- a/spec/features/issuables/default_sort_order_spec.rb +++ b/spec/features/issuables/default_sort_order_spec.rb @@ -40,10 +40,10 @@ describe 'Projects > Issuables > Default sort order' do context 'in the "merge requests / open" tab', js: true do let(:issuable_type) { :merge_request } - it 'is "last created"' do + it 'is "created date"' do visit_merge_requests_with_state(project, 'open') - expect(selected_sort_order).to eq('last created') + expect(selected_sort_order).to eq('created date') expect(first_merge_request).to include(last_created_issuable.title) expect(last_merge_request).to include(first_created_issuable.title) end @@ -76,10 +76,10 @@ describe 'Projects > Issuables > Default sort order' do context 'in the "merge requests / all" tab', js: true do let(:issuable_type) { :merge_request } - it 'is "last created"' do + it 'is "created date"' do visit_merge_requests_with_state(project, 'all') - expect(find('.issues-other-filters')).to have_content('Last created') + expect(find('.issues-other-filters')).to have_content('Created date') expect(first_merge_request).to include(last_created_issuable.title) expect(last_merge_request).to include(first_created_issuable.title) end @@ -105,10 +105,10 @@ describe 'Projects > Issuables > Default sort order' do context 'in the "issues" tab', js: true do let(:issuable_type) { :issue } - it 'is "last created"' do + it 'is "created date"' do visit_issues project - expect(find('.issues-other-filters')).to have_content('Last created') + expect(find('.issues-other-filters')).to have_content('Created date') expect(first_issue).to include(last_created_issuable.title) expect(last_issue).to include(first_created_issuable.title) end @@ -117,10 +117,10 @@ describe 'Projects > Issuables > Default sort order' do context 'in the "issues / open" tab', js: true do let(:issuable_type) { :issue } - it 'is "last created"' do + it 'is "created date"' do visit_issues_with_state(project, 'open') - expect(find('.issues-other-filters')).to have_content('Last created') + expect(find('.issues-other-filters')).to have_content('Created date') expect(first_issue).to include(last_created_issuable.title) expect(last_issue).to include(first_created_issuable.title) end @@ -141,10 +141,10 @@ describe 'Projects > Issuables > Default sort order' do context 'in the "issues / all" tab', js: true do let(:issuable_type) { :issue } - it 'is "last created"' do + it 'is "created date"' do visit_issues_with_state(project, 'all') - expect(find('.issues-other-filters')).to have_content('Last created') + expect(find('.issues-other-filters')).to have_content('Created date') expect(first_issue).to include(last_created_issuable.title) expect(last_issue).to include(first_created_issuable.title) end @@ -157,26 +157,12 @@ describe 'Projects > Issuables > Default sort order' do visit_issues(project, sort: 'id_desc') end - it 'shows the sort order as last created' do - expect(find('.issues-other-filters')).to have_content('Last created') + it 'shows the sort order as created date' do + expect(find('.issues-other-filters')).to have_content('Created date') expect(first_issue).to include(last_created_issuable.title) expect(last_issue).to include(first_created_issuable.title) end end - - context 'when the sort in the URL is id_asc' do - let(:issuable_type) { :issue } - - before do - visit_issues(project, sort: 'id_asc') - end - - it 'shows the sort order as oldest created' do - expect(find('.issues-other-filters')).to have_content('Oldest created') - expect(first_issue).to include(first_created_issuable.title) - expect(last_issue).to include(last_created_issuable.title) - end - end end def selected_sort_order diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb index 82fde8e0599d50343fd8cd652ce5be9b01cf8201..a84d129b3b4b2573266f1e33879b80184dc87748 100644 --- a/spec/features/issues/filtered_search/filter_issues_spec.rb +++ b/spec/features/issues/filtered_search/filter_issues_spec.rb @@ -422,20 +422,18 @@ describe 'Filter issues', js: true do end context 'sorting' do - it 'sorts by oldest updated' do - create(:issue, + it 'sorts by created date' do + new_issue = create(:issue, title: '3 days ago', project: project, author: user, - created_at: 3.days.ago, - updated_at: 3.days.ago) + created_at: 3.days.ago) - old_issue = create(:issue, + create(:issue, title: '5 days ago', project: project, author: user, - created_at: 5.days.ago, - updated_at: 5.days.ago) + created_at: 5.days.ago) input_filtered_search('days ago') @@ -444,10 +442,10 @@ describe 'Filter issues', js: true do sort_toggle = find('.filtered-search-wrapper .dropdown-toggle') sort_toggle.click - find('.filtered-search-wrapper .dropdown-menu li a', text: 'Oldest updated').click + find('.filtered-search-wrapper .dropdown-menu li a', text: 'Created date').click wait_for_requests - expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(old_issue.title) + expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(new_issue.title) end end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index c57793afdf5bd97daf55f51fa4814b98cf693e95..a2cd4c28448a40a26bdab633900ab144cbab3c27 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -201,19 +201,12 @@ describe 'Issues' do let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } it 'sorts by newest' do - visit project_issues_path(project, sort: sort_value_recently_created) + visit project_issues_path(project, sort: sort_value_created_date) expect(first_issue).to include('foo') expect(last_issue).to include('baz') end - it 'sorts by oldest' do - visit project_issues_path(project, sort: sort_value_oldest_created) - - expect(first_issue).to include('baz') - expect(last_issue).to include('foo') - end - it 'sorts by most recently updated' do baz.updated_at = Time.now + 100 baz.save @@ -222,36 +215,22 @@ describe 'Issues' do expect(first_issue).to include('baz') end - it 'sorts by least recently updated' do - baz.updated_at = Time.now - 100 - baz.save - visit project_issues_path(project, sort: sort_value_oldest_updated) - - expect(first_issue).to include('baz') - end - describe 'sorting by due date' do before do foo.update(due_date: 1.day.from_now) bar.update(due_date: 6.days.from_now) end - it 'sorts by recently due date' do - visit project_issues_path(project, sort: sort_value_due_date_soon) + it 'sorts by due date' do + visit project_issues_path(project, sort: sort_value_due_date) expect(first_issue).to include('foo') end - it 'sorts by least recently due date' do - visit project_issues_path(project, sort: sort_value_due_date_later) - - expect(first_issue).to include('bar') - end - - it 'sorts by least recently due date by excluding nil due dates' do + it 'sorts by due date by excluding nil due dates' do bar.update(due_date: nil) - visit project_issues_path(project, sort: sort_value_due_date_later) + visit project_issues_path(project, sort: sort_value_due_date) expect(first_issue).to include('foo') end @@ -350,19 +329,12 @@ describe 'Issues' do bar.save end - it 'sorts by recently due milestone' do - visit project_issues_path(project, sort: sort_value_milestone_soon) + it 'sorts by milestone' do + visit project_issues_path(project, sort: sort_value_milestone) expect(first_issue).to include('foo') expect(last_issue).to include('baz') end - - it 'sorts by least recently due milestone' do - visit project_issues_path(project, sort: sort_value_milestone_later) - - expect(first_issue).to include('bar') - expect(last_issue).to include('baz') - end end describe 'combine filter and sort' do @@ -376,13 +348,11 @@ describe 'Issues' do end it 'sorts with a filter applied' do - visit project_issues_path(project, - sort: sort_value_oldest_created, - assignee_id: user2.id) + visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id) - expect(first_issue).to include('bar') - expect(last_issue).to include('foo') - expect(page).not_to have_content 'baz' + expect(first_issue).to include('foo') + expect(last_issue).to include('bar') + expect(page).not_to have_content('baz') end end end diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb index b51ae0890e43ac964a1afd98ebbe94a45e666d16..16703bc1c01cf2aca579a877fb2ff383688f7c97 100644 --- a/spec/features/merge_requests/filter_merge_requests_spec.rb +++ b/spec/features/merge_requests/filter_merge_requests_spec.rb @@ -277,9 +277,9 @@ describe 'Filter merge requests' do expect_mr_list_count(2) - click_button 'Last created' + click_button 'Created date' page.within '.dropdown-menu-sort' do - click_link 'Oldest created' + click_link 'Priority' end wait_for_requests diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb index 20008b4e7f91cb252131ff5dbc6c27881194404c..416a0f78a4573bbe8d3be533b3a9ecc676782409 100644 --- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -52,21 +52,13 @@ describe 'Projects > Merge requests > User lists merge requests' do end it 'sorts by newest' do - visit_merge_requests(project, sort: sort_value_recently_created) + visit_merge_requests(project, sort: sort_value_created_date) expect(first_merge_request).to include('fix') expect(last_merge_request).to include('merge-test') expect(count_merge_requests).to eq(3) end - it 'sorts by oldest' do - visit_merge_requests(project, sort: sort_value_oldest_created) - - expect(first_merge_request).to include('merge-test') - expect(last_merge_request).to include('fix') - expect(count_merge_requests).to eq(3) - end - it 'sorts by last updated' do visit_merge_requests(project, sort: sort_value_recently_updated) @@ -74,33 +66,19 @@ describe 'Projects > Merge requests > User lists merge requests' do expect(count_merge_requests).to eq(3) end - it 'sorts by oldest updated' do - visit_merge_requests(project, sort: sort_value_oldest_updated) - - expect(first_merge_request).to include('markdown') - expect(count_merge_requests).to eq(3) - end - - it 'sorts by milestone due soon' do - visit_merge_requests(project, sort: sort_value_milestone_soon) + it 'sorts by milestone' do + visit_merge_requests(project, sort: sort_value_milestone) expect(first_merge_request).to include('fix') expect(count_merge_requests).to eq(3) end - it 'sorts by milestone due later' do - visit_merge_requests(project, sort: sort_value_milestone_later) - - expect(first_merge_request).to include('markdown') - expect(count_merge_requests).to eq(3) - end - - it 'filters on one label and sorts by due soon' do + it 'filters on one label and sorts by due date' do label = create(:label, project: project) create(:label_link, label: label, target: @fix) visit_merge_requests(project, label_name: [label.name], - sort: sort_value_due_date_soon) + sort: sort_value_due_date) expect(first_merge_request).to include('fix') expect(count_merge_requests).to eq(1) @@ -115,9 +93,9 @@ describe 'Projects > Merge requests > User lists merge requests' do create(:label_link, label: label2, target: @fix) end - it 'sorts by due soon' do + it 'sorts by due date' do visit_merge_requests(project, label_name: [label.name, label2.name], - sort: sort_value_due_date_soon) + sort: sort_value_due_date) expect(first_merge_request).to include('fix') expect(count_merge_requests).to eq(1) @@ -127,7 +105,7 @@ describe 'Projects > Merge requests > User lists merge requests' do it 'sorts by due soon' do visit_merge_requests(project, label_name: [label.name, label2.name], assignee_id: user.id, - sort: sort_value_due_date_soon) + sort: sort_value_due_date) expect(first_merge_request).to include('fix') expect(count_merge_requests).to eq(1) @@ -137,7 +115,7 @@ describe 'Projects > Merge requests > User lists merge requests' do visit project_merge_requests_path(project, label_name: [label.name, label2.name], assignee_id: user.id, - sort: sort_value_milestone_soon) + sort: sort_value_milestone) expect(first_merge_request).to include('fix') end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 547daa605bf8a8a0c7e0429246b1ddba656947e7..9de856e19595a9467faceacc03a3f7298b5d31f8 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -1,28 +1,27 @@ require 'spec_helper' describe ProjectPolicy do - let(:guest) { create(:user) } - let(:reporter) { create(:user) } - let(:dev) { create(:user) } - let(:master) { create(:user) } - let(:owner) { create(:user) } - let(:auditor) { create(:user, :auditor) } - let(:admin) { create(:admin) } + set(:guest) { create(:user) } + set(:reporter) { create(:user) } + set(:developer) { create(:user) } + set(:master) { create(:user) } + set(:owner) { create(:user) } + set(:admin) { create(:admin) } let(:project) { create(:project, :public, namespace: owner.namespace) } - let(:guest_permissions) do + let(:base_guest_permissions) do %i[ read_project read_board read_list read_wiki read_issue read_label - read_issue_link read_milestone read_project_snippet read_project_member + read_milestone read_project_snippet read_project_member read_note create_project create_issue create_note upload_file ] end - let(:reporter_permissions) do + let(:base_reporter_permissions) do %i[ download_code fork_project create_project_snippet update_issue - admin_issue admin_label admin_issue_link admin_list read_commit_status read_build + admin_issue admin_label admin_list read_commit_status read_build read_container_image read_pipeline read_environment read_deployment read_merge_request download_wiki_code ] @@ -42,10 +41,9 @@ describe ProjectPolicy do ] end - let(:master_permissions) do + let(:base_master_permissions) do %i[ - push_code_to_protected_branches delete_protected_branch - update_project_snippet update_environment + delete_protected_branch update_project_snippet update_environment update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project admin_commit_status admin_build admin_container_image @@ -68,21 +66,20 @@ describe ProjectPolicy do ] end - let(:auditor_permissions) do - %i[ - download_code download_wiki_code read_project read_board read_list - read_wiki read_issue read_label read_issue_link read_milestone read_project_snippet - read_project_member read_note read_cycle_analytics read_pipeline - read_build read_commit_status read_container_image read_environment - read_deployment read_merge_request read_pages - ] - end + # Used in EE specs + let(:additional_guest_permissions) { [] } + let(:additional_reporter_permissions) { [] } + let(:additional_master_permissions) { [] } + + let(:guest_permissions) { base_guest_permissions + additional_guest_permissions } + let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions } + let(:master_permissions) { base_master_permissions + additional_master_permissions } before do - project.team << [guest, :guest] - project.team << [master, :master] - project.team << [dev, :developer] - project.team << [reporter, :reporter] + project.add_guest(guest) + project.add_master(master) + project.add_developer(developer) + project.add_reporter(reporter) end def expect_allowed(*permissions) @@ -139,38 +136,41 @@ describe ProjectPolicy do end end - context 'when a project has pending invites, and the current user is anonymous' do - let(:group) { create(:group, :public) } - let(:project) { create(:project, :public, namespace: group) } - let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] } - let(:anonymous_permissions) { guest_permissions - user_permissions } + shared_examples 'project policies as anonymous' do + context 'abilities for public projects' do + context 'when a project has pending invites' do + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, namespace: group) } + let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] } + let(:anonymous_permissions) { guest_permissions - user_permissions } - subject { described_class.new(nil, project) } + subject { described_class.new(nil, project) } - before do - create(:group_member, :invited, group: group) - end + before do + create(:group_member, :invited, group: group) + end - it 'does not grant owner access' do - expect_allowed(*anonymous_permissions) - expect_disallowed(*user_permissions) + it 'does not grant owner access' do + expect_allowed(*anonymous_permissions) + expect_disallowed(*user_permissions) + end + end end - end - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } - subject { described_class.new(current_user, project) } - - context 'with no user' do - let(:current_user) { nil } + subject { described_class.new(nil, project) } it { is_expected.to be_banned } end + end - context 'guests' do - let(:current_user) { guest } + shared_examples 'project policies as guest' do + subject { described_class.new(guest, project) } + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } let(:reporter_public_build_permissions) do reporter_permissions - [:read_build, :read_pipeline] end @@ -191,7 +191,7 @@ describe ProjectPolicy do end end - context 'public builds disabled' do + context 'when public builds disabled' do before do project.update(public_builds: false) end @@ -204,8 +204,7 @@ describe ProjectPolicy do context 'when builds are disabled' do before do - project.project_feature.update( - builds_access_level: ProjectFeature::DISABLED) + project.project_feature.update(builds_access_level: ProjectFeature::DISABLED) end it do @@ -214,9 +213,13 @@ describe ProjectPolicy do end end end + end - context 'reporter' do - let(:current_user) { reporter } + shared_examples 'project policies as reporter' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(reporter, project) } it do expect_allowed(*guest_permissions) @@ -228,9 +231,13 @@ describe ProjectPolicy do expect_disallowed(*owner_permissions) end end + end - context 'developer' do - let(:current_user) { dev } + shared_examples 'project policies as developer' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(developer, project) } it do expect_allowed(*guest_permissions) @@ -241,9 +248,13 @@ describe ProjectPolicy do expect_disallowed(*owner_permissions) end end + end - context 'master' do - let(:current_user) { master } + shared_examples 'project policies as master' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(master, project) } it do expect_allowed(*guest_permissions) @@ -254,9 +265,13 @@ describe ProjectPolicy do expect_disallowed(*owner_permissions) end end + end + + shared_examples 'project policies as owner' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } - context 'owner' do - let(:current_user) { owner } + subject { described_class.new(owner, project) } it do expect_allowed(*guest_permissions) @@ -267,9 +282,13 @@ describe ProjectPolicy do expect_allowed(*owner_permissions) end end + end + + shared_examples 'project policies as admin' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } - context 'admin' do - let(:current_user) { admin } + subject { described_class.new(admin, project) } it do expect_allowed(*guest_permissions) @@ -280,11 +299,44 @@ describe ProjectPolicy do expect_allowed(*owner_permissions) end end + end + + it_behaves_like 'project policies as anonymous' + it_behaves_like 'project policies as guest' + it_behaves_like 'project policies as reporter' + it_behaves_like 'project policies as developer' + it_behaves_like 'project policies as master' + it_behaves_like 'project policies as owner' + it_behaves_like 'project policies as admin' + + context 'EE' do + let(:additional_guest_permissions) { [:read_issue_link] } + let(:additional_reporter_permissions) { [:admin_issue_link]} + let(:additional_master_permissions) { [:push_code_to_protected_branches] } + let(:auditor_permissions) do + %i[ + download_code download_wiki_code read_project read_board read_list + read_wiki read_issue read_label read_issue_link read_milestone read_project_snippet + read_project_member read_note read_cycle_analytics read_pipeline + read_build read_commit_status read_container_image read_environment + read_deployment read_merge_request read_pages + ] + end + + it_behaves_like 'project policies as anonymous' + it_behaves_like 'project policies as guest' + it_behaves_like 'project policies as reporter' + it_behaves_like 'project policies as developer' + it_behaves_like 'project policies as master' + it_behaves_like 'project policies as owner' + it_behaves_like 'project policies as admin' context 'auditor' do - let(:current_user) { auditor } + let(:auditor) { create(:user, :auditor) } + + subject { described_class.new(auditor, project) } - context 'not a team member' do + context 'who is not a team member' do it do is_expected.to be_disallowed(*developer_permissions) is_expected.to be_disallowed(*master_permissions) @@ -294,9 +346,9 @@ describe ProjectPolicy do end end - context 'team member' do + context 'who is a team member' do before do - project.team << [auditor, :guest] + project.add_guest(auditor) end it do diff --git a/spec/services/geo/node_status_service_spec.rb b/spec/services/geo/node_status_service_spec.rb index ab015ccedd8eb816771b00e1c359bfec3ba66db6..3588ee71d70c0bc6239579da2acd17d30b5c4828 100644 --- a/spec/services/geo/node_status_service_spec.rb +++ b/spec/services/geo/node_status_service_spec.rb @@ -57,6 +57,23 @@ describe Geo::NodeStatusService do expect(status.health).to eq("Could not connect to Geo node - HTTP Status Code: 401 Unauthorized\n") end + it 'alerts on bad SSL certficate' do + message = 'bad certificate' + allow(described_class).to receive(:get).and_raise(OpenSSL::SSL::SSLError.new(message)) + + status = subject.call(secondary) + + expect(status.health).to eq(message) + end + + it 'handles connection refused' do + allow(described_class).to receive(:get).and_raise(Errno::ECONNREFUSED.new('bad connection')) + + status = subject.call(secondary) + + expect(status.health).to eq('Connection refused - bad connection') + end + it 'returns meaningful error message when primary uses incorrect db key' do secondary # create it before mocking GeoNode#secret_access_key