diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-05 12:06:20 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-05 12:06:20 +0000 |
commit | 791785af5540d18eaa97da24f9ff8638e1960b72 (patch) | |
tree | caeb6f08d9cc10a0052dc6851b46653d94c29022 | |
parent | a92d6b36c2d2892e8c070efb169f0c06815900ee (diff) | |
download | gitlab-ce-791785af5540d18eaa97da24f9ff8638e1960b72.tar.gz |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/finders/branches_finder.rb | 51 | ||||
-rw-r--r-- | app/finders/git_refs_finder.rb | 56 | ||||
-rw-r--r-- | app/finders/tags_finder.rb | 28 | ||||
-rw-r--r-- | app/models/notification_reason.rb | 4 | ||||
-rw-r--r-- | app/models/user.rb | 3 | ||||
-rw-r--r-- | app/services/notification_recipient_service.rb | 4 | ||||
-rw-r--r-- | changelogs/unreleased/34416-subscribed-notification-header.yml | 5 | ||||
-rw-r--r-- | changelogs/unreleased/CauhxMilloy-gitlab-addStartEndMarkersForTagsSearch.yml | 5 | ||||
-rw-r--r-- | changelogs/unreleased/render-html-tags-in-job-log.yml | 5 | ||||
-rw-r--r-- | doc/api/branches.md | 2 | ||||
-rw-r--r-- | doc/api/tags.md | 2 | ||||
-rw-r--r-- | lib/gitlab/ci/ansi2json/converter.rb | 4 | ||||
-rw-r--r-- | spec/finders/branches_finder_spec.rb | 56 | ||||
-rw-r--r-- | spec/finders/tags_finder_spec.rb | 38 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/ansi2json_spec.rb | 8 | ||||
-rw-r--r-- | spec/services/notification_service_spec.rb | 23 |
16 files changed, 188 insertions, 106 deletions
diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb index 291a24c1405..8001c70a9b2 100644 --- a/app/finders/branches_finder.rb +++ b/app/finders/branches_finder.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -class BranchesFinder +class BranchesFinder < GitRefsFinder def initialize(repository, params = {}) - @repository = repository - @params = params + super(repository, params) end def execute @@ -15,56 +14,10 @@ class BranchesFinder private - attr_reader :repository, :params - def names @params[:names].presence end - def search - @params[:search].presence - end - - def sort - @params[:sort].presence || 'name' - end - - def by_search(branches) - return branches unless search - - case search - when ->(v) { v.starts_with?('^') } - filter_branches_with_prefix(branches, search.slice(1..-1).upcase) - when ->(v) { v.ends_with?('$') } - filter_branches_with_suffix(branches, search.chop.upcase) - else - matches = filter_branches_by_name(branches, search.upcase) - set_exact_match_as_first_result(matches, search) - end - end - - def filter_branches_with_prefix(branches, prefix) - branches.select { |branch| branch.name.upcase.starts_with?(prefix) } - end - - def filter_branches_with_suffix(branches, suffix) - branches.select { |branch| branch.name.upcase.ends_with?(suffix) } - end - - def filter_branches_by_name(branches, term) - branches.select { |branch| branch.name.upcase.include?(term) } - end - - def set_exact_match_as_first_result(matches, term) - exact_match_index = find_exact_match_index(matches, term) - matches.insert(0, matches.delete_at(exact_match_index)) if exact_match_index - matches - end - - def find_exact_match_index(matches, term) - matches.index { |branch| branch.name.casecmp(term) == 0 } - end - def by_names(branches) return branches unless names diff --git a/app/finders/git_refs_finder.rb b/app/finders/git_refs_finder.rb new file mode 100644 index 00000000000..2289b34e562 --- /dev/null +++ b/app/finders/git_refs_finder.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +class GitRefsFinder + def initialize(repository, params = {}) + @repository = repository + @params = params + end + + protected + + attr_reader :repository, :params + + def search + @params[:search].presence + end + + def sort + @params[:sort].presence || 'name' + end + + def by_search(refs) + return refs unless search + + case search + when ->(v) { v.starts_with?('^') } + filter_refs_with_prefix(refs, search.slice(1..-1)) + when ->(v) { v.ends_with?('$') } + filter_refs_with_suffix(refs, search.chop) + else + matches = filter_refs_by_name(refs, search) + set_exact_match_as_first_result(matches, search) + end + end + + def filter_refs_with_prefix(refs, prefix) + refs.select { |ref| ref.name.upcase.starts_with?(prefix.upcase) } + end + + def filter_refs_with_suffix(refs, suffix) + refs.select { |ref| ref.name.upcase.ends_with?(suffix.upcase) } + end + + def filter_refs_by_name(refs, term) + refs.select { |ref| ref.name.upcase.include?(term.upcase) } + end + + def set_exact_match_as_first_result(matches, term) + exact_match_index = find_exact_match_index(matches, term) + matches.insert(0, matches.delete_at(exact_match_index)) if exact_match_index + matches + end + + def find_exact_match_index(matches, term) + matches.index { |ref| ref.name.casecmp(term) == 0 } + end +end diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb index 2ffd46245e9..fd58f478b45 100644 --- a/app/finders/tags_finder.rb +++ b/app/finders/tags_finder.rb @@ -1,31 +1,13 @@ # frozen_string_literal: true -class TagsFinder +class TagsFinder < GitRefsFinder def initialize(repository, params) - @repository = repository - @params = params + super(repository, params) end def execute - tags = @repository.tags_sorted_by(sort) - filter_by_name(tags) - end - - private - - def sort - @params[:sort].presence - end - - def search - @params[:search].presence - end - - def filter_by_name(tags) - if search - tags.select { |tag| tag.name.include?(search) } - else - tags - end + tags = repository.tags_sorted_by(sort) + tags = by_search(tags) + tags end end diff --git a/app/models/notification_reason.rb b/app/models/notification_reason.rb index 6856d397413..a7967239417 100644 --- a/app/models/notification_reason.rb +++ b/app/models/notification_reason.rb @@ -6,12 +6,14 @@ class NotificationReason OWN_ACTIVITY = 'own_activity' ASSIGNED = 'assigned' MENTIONED = 'mentioned' + SUBSCRIBED = 'subscribed' # Priority list for selecting which reason to return in the notification REASON_PRIORITY = [ OWN_ACTIVITY, ASSIGNED, - MENTIONED + MENTIONED, + SUBSCRIBED ].freeze # returns the priority of a reason as an integer diff --git a/app/models/user.rb b/app/models/user.rb index eec8ad6edbb..277d73cc2ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,9 +56,6 @@ class User < ApplicationRecord BLOCKED_MESSAGE = "Your account has been blocked. Please contact your GitLab " \ "administrator if you think this is an error." - # Removed in GitLab 12.3. Keep until after 2019-09-22. - self.ignored_columns += %i[support_bot] - MINIMUM_INACTIVE_DAYS = 180 # Override Devise::Models::Trackable#update_tracked_fields! diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 9afbb678f5d..0bdf6a0e6bc 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -181,7 +181,7 @@ module NotificationRecipientService def add_subscribed_users return unless target.respond_to? :subscribers - add_recipients(target.subscribers(project), :subscription, nil) + add_recipients(target.subscribers(project), :subscription, NotificationReason::SUBSCRIBED) end # rubocop: disable CodeReuse/ActiveRecord @@ -240,7 +240,7 @@ module NotificationRecipientService return unless target.respond_to? :labels (labels || target.labels).each do |label| - add_recipients(label.subscribers(project), :subscription, nil) + add_recipients(label.subscribers(project), :subscription, NotificationReason::SUBSCRIBED) end end end diff --git a/changelogs/unreleased/34416-subscribed-notification-header.yml b/changelogs/unreleased/34416-subscribed-notification-header.yml new file mode 100644 index 00000000000..dd1fca4255b --- /dev/null +++ b/changelogs/unreleased/34416-subscribed-notification-header.yml @@ -0,0 +1,5 @@ +--- +title: Set X-GitLab-NotificationReason header if notification reason is explicit subscription +merge_request: 18812 +author: +type: added diff --git a/changelogs/unreleased/CauhxMilloy-gitlab-addStartEndMarkersForTagsSearch.yml b/changelogs/unreleased/CauhxMilloy-gitlab-addStartEndMarkersForTagsSearch.yml new file mode 100644 index 00000000000..e06f7868a34 --- /dev/null +++ b/changelogs/unreleased/CauhxMilloy-gitlab-addStartEndMarkersForTagsSearch.yml @@ -0,0 +1,5 @@ +--- +title: Adding support for searching tags using '^' and '$' +merge_request: 19435 +author: Cauhx Milloy +type: added diff --git a/changelogs/unreleased/render-html-tags-in-job-log.yml b/changelogs/unreleased/render-html-tags-in-job-log.yml new file mode 100644 index 00000000000..cbdcf4e6610 --- /dev/null +++ b/changelogs/unreleased/render-html-tags-in-job-log.yml @@ -0,0 +1,5 @@ +--- +title: Do not escape HTML tags in Ansi2json as they are escaped in the frontend +merge_request: 19610 +author: +type: fixed diff --git a/doc/api/branches.md b/doc/api/branches.md index 31c8add300d..bba8876163e 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -21,7 +21,7 @@ Parameters: | Attribute | Type | Required | Description | |:----------|:---------------|:---------|:------------| | `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.| -| `search` | string | no | Return list of branches containing the search string. You can use `^term` and `term$` to find branches that begin and end with `term` respectively.| +| `search` | string | no | Return list of branches containing the search string. You can use `^term` and `term$` to find branches that begin and end with `term` respectively. | Example request: diff --git a/doc/api/tags.md b/doc/api/tags.md index 56143969e3c..13c4b83dda8 100644 --- a/doc/api/tags.md +++ b/doc/api/tags.md @@ -17,7 +17,7 @@ Parameters: | `id` | integer/string| yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user| | `order_by` | string | no | Return tags ordered by `name` or `updated` fields. Default is `updated` | | `sort` | string | no | Return tags sorted in `asc` or `desc` order. Default is `desc` | -| `search` | string | no | Return list of tags matching the search criteria | +| `search` | string | no | Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. | > Support for `search` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/54401) in GitLab 11.8. diff --git a/lib/gitlab/ci/ansi2json/converter.rb b/lib/gitlab/ci/ansi2json/converter.rb index 908e560999e..cbda3808b86 100644 --- a/lib/gitlab/ci/ansi2json/converter.rb +++ b/lib/gitlab/ci/ansi2json/converter.rb @@ -66,14 +66,12 @@ module Gitlab elsif scan_token(scanner, /\e(([@-_])(.*?)?)?$/) # stop scanning scanner.terminate - elsif scan_token(scanner, /</) - @state.current_line << '<' elsif scan_token(scanner, /\r?\n/) flush_current_line elsif scan_token(scanner, /\r/) # drop last line @state.current_line.clear! - elsif scan_token(scanner, /.[^\e<\r\ns]*/m) + elsif scan_token(scanner, /.[^\e\r\ns]*/m) # this is a join from all previous tokens and first letters # it always matches at least one character `.` # it matches everything that is not start of: diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb index 1a33bdf11d7..70b5da0cc3c 100644 --- a/spec/finders/branches_finder_spec.rb +++ b/spec/finders/branches_finder_spec.rb @@ -73,58 +73,76 @@ describe BranchesFinder do expect(result.count).to eq(3) expect(result.map(&:name)).to eq(%w{csv fix lfs}) end - end - context 'filter and sort' do - it 'filters branches by name and sorts by recently_updated' do - params = { sort: 'updated_desc', search: 'feat' } + it 'filters branches by name that begins with' do + params = { search: '^feature_' } branches_finder = described_class.new(repository, params) result = branches_finder.execute expect(result.first.name).to eq('feature_conflict') - expect(result.count).to eq(2) + expect(result.count).to eq(1) end - it 'filters branches by name and sorts by recently_updated, with exact matches first' do - params = { sort: 'updated_desc', search: 'feature' } + it 'filters branches by name that ends with' do + params = { search: 'feature$' } branches_finder = described_class.new(repository, params) result = branches_finder.execute expect(result.first.name).to eq('feature') - expect(result.second.name).to eq('feature_conflict') - expect(result.count).to eq(2) + expect(result.count).to eq(1) end - it 'filters branches by name and sorts by last_updated' do - params = { sort: 'updated_asc', search: 'feature' } + it 'filters branches by nonexistent name that begins with' do + params = { search: '^nope' } branches_finder = described_class.new(repository, params) result = branches_finder.execute - expect(result.first.name).to eq('feature') - expect(result.count).to eq(2) + expect(result.count).to eq(0) end - it 'filters branches by name that begins with' do - params = { search: '^feature_' } + it 'filters branches by nonexistent name that ends with' do + params = { search: 'nope$' } + branches_finder = described_class.new(repository, params) + + result = branches_finder.execute + + expect(result.count).to eq(0) + end + end + + context 'filter and sort' do + it 'filters branches by name and sorts by recently_updated' do + params = { sort: 'updated_desc', search: 'feat' } branches_finder = described_class.new(repository, params) result = branches_finder.execute expect(result.first.name).to eq('feature_conflict') - expect(result.count).to eq(1) + expect(result.count).to eq(2) end - it 'filters branches by name that ends with' do - params = { search: 'feature$' } + it 'filters branches by name and sorts by recently_updated, with exact matches first' do + params = { sort: 'updated_desc', search: 'feature' } branches_finder = described_class.new(repository, params) result = branches_finder.execute expect(result.first.name).to eq('feature') - expect(result.count).to eq(1) + expect(result.second.name).to eq('feature_conflict') + expect(result.count).to eq(2) + end + + it 'filters branches by name and sorts by last_updated' do + params = { sort: 'updated_asc', search: 'feature' } + branches_finder = described_class.new(repository, params) + + result = branches_finder.execute + + expect(result.first.name).to eq('feature') + expect(result.count).to eq(2) end end end diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb index 85f970b71c4..e9f29ab2441 100644 --- a/spec/finders/tags_finder_spec.rb +++ b/spec/finders/tags_finder_spec.rb @@ -54,6 +54,44 @@ describe TagsFinder do expect(result.count).to eq(0) end + + it 'filters tags by name that begins with' do + params = { search: '^v1.0' } + tags_finder = described_class.new(repository, params) + + result = tags_finder.execute + + expect(result.first.name).to eq('v1.0.0') + expect(result.count).to eq(1) + end + + it 'filters tags by name that ends with' do + params = { search: '0.0$' } + tags_finder = described_class.new(repository, params) + + result = tags_finder.execute + + expect(result.first.name).to eq('v1.0.0') + expect(result.count).to eq(1) + end + + it 'filters tags by nonexistent name that begins with' do + params = { search: '^nope' } + tags_finder = described_class.new(repository, params) + + result = tags_finder.execute + + expect(result.count).to eq(0) + end + + it 'filters tags by nonexistent name that ends with' do + params = { search: 'nope$' } + tags_finder = described_class.new(repository, params) + + result = tags_finder.execute + + expect(result.count).to eq(0) + end end context 'filter and sort' do diff --git a/spec/lib/gitlab/ci/ansi2json_spec.rb b/spec/lib/gitlab/ci/ansi2json_spec.rb index 3cd448d1aae..124379fa321 100644 --- a/spec/lib/gitlab/ci/ansi2json_spec.rb +++ b/spec/lib/gitlab/ci/ansi2json_spec.rb @@ -224,17 +224,17 @@ describe Gitlab::Ci::Ansi2json do end end - it 'prevents XSS injection' do - trace = "#{section_start}section_end:1:2<script>alert('XSS Hack!');</script>#{section_end}" + it 'prints HTML tags as is' do + trace = "#{section_start}section_end:1:2<div>hello</div>#{section_end}" expect(convert_json(trace)).to eq([ { offset: 0, - content: [{ text: "section_end:1:2<script>alert('XSS Hack!');</script>" }], + content: [{ text: "section_end:1:2<div>hello</div>" }], section: 'prepare-script', section_header: true }, { - offset: 95, + offset: 75, content: [], section: 'prepare-script', section_duration: '01:03' diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 2481cd5c006..25900043f11 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -869,6 +869,18 @@ describe NotificationService, :mailer do should_email(user_4) end + it 'adds "subscribed" reason to subscriber emails' do + user_1 = create(:user) + label = create(:label, project: project, issues: [issue]) + issue.reload + label.subscribe(user_1) + + notification.new_issue(issue, @u_disabled) + + email = find_email_for(user_1) + expect(email).to have_header('X-GitLab-NotificationReason', NotificationReason::SUBSCRIBED) + end + it_behaves_like 'project emails are disabled' do let(:notification_target) { issue } let(:notification_trigger) { notification.new_issue(issue, @u_disabled) } @@ -1272,6 +1284,17 @@ describe NotificationService, :mailer do let(:notification_target) { issue } let(:notification_trigger) { notification.close_issue(issue, @u_disabled) } end + + it 'adds "subscribed" reason to subscriber emails' do + user_1 = create(:user) + issue.subscribe(user_1) + issue.reload + + notification.close_issue(issue, @u_disabled) + + email = find_email_for(user_1) + expect(email).to have_header('X-GitLab-NotificationReason', NotificationReason::SUBSCRIBED) + end end describe '#reopen_issue' do |