Merge branch 'ce-revert-d5ce84fd' into 'master'
Revert "Merge branch 'revert-82d7b5a0-ce' into 'master'" Closes #57857 and #50747 See merge request gitlab-org/gitlab-ce!25559
This commit is contained in:
commit
13c723f1dd
|
@ -96,6 +96,11 @@ export default class FilteredSearchDropdownManager {
|
|||
gl: DropdownNonUser,
|
||||
element: this.container.querySelector('#js-dropdown-wip'),
|
||||
},
|
||||
confidential: {
|
||||
reference: null,
|
||||
gl: DropdownNonUser,
|
||||
element: this.container.querySelector('#js-dropdown-confidential'),
|
||||
},
|
||||
status: {
|
||||
reference: null,
|
||||
gl: NullDropdown,
|
||||
|
|
|
@ -72,6 +72,23 @@ export default class FilteredSearchTokenKeys {
|
|||
);
|
||||
}
|
||||
|
||||
addExtraTokensForIssues() {
|
||||
const confidentialToken = {
|
||||
key: 'confidential',
|
||||
type: 'string',
|
||||
param: '',
|
||||
symbol: '',
|
||||
icon: 'eye-slash',
|
||||
tag: 'Yes or No',
|
||||
lowercaseValueOnSubmit: true,
|
||||
uppercaseTokenName: false,
|
||||
capitalizeTokenValue: true,
|
||||
};
|
||||
|
||||
this.tokenKeys.push(confidentialToken);
|
||||
this.tokenKeysWithAlternative.push(confidentialToken);
|
||||
}
|
||||
|
||||
addExtraTokensForMergeRequests() {
|
||||
const wipToken = {
|
||||
key: 'wip',
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import projectSelect from '~/project_select';
|
||||
import initFilteredSearch from '~/pages/search/init_filtered_search';
|
||||
import { FILTERED_SEARCH } from '~/pages/constants';
|
||||
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
|
||||
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
|
||||
|
||||
initFilteredSearch({
|
||||
page: FILTERED_SEARCH.ISSUES,
|
||||
isGroupDecendent: true,
|
||||
|
|
|
@ -4,11 +4,13 @@ import IssuableIndex from '~/issuable_index';
|
|||
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
|
||||
import UsersSelect from '~/users_select';
|
||||
import initFilteredSearch from '~/pages/search/init_filtered_search';
|
||||
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
|
||||
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
|
||||
import { FILTERED_SEARCH } from '~/pages/constants';
|
||||
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
|
||||
|
||||
initFilteredSearch({
|
||||
page: FILTERED_SEARCH.ISSUES,
|
||||
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
|
||||
|
|
|
@ -11,7 +11,7 @@ export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES);
|
|||
/**
|
||||
* Fetches the main endpoint.
|
||||
* Will dispatch requestNamespace action before starting the request.
|
||||
* Will dispatch receiveNamespaceSuccess if the request is successfull
|
||||
* Will dispatch receiveNamespaceSuccess if the request is successful
|
||||
* Will dispatch receiveNamesapceError if the request returns an error
|
||||
*
|
||||
* @param {String} projectId
|
||||
|
|
|
@ -24,7 +24,7 @@ class Clusters::ClustersController < Clusters::BaseController
|
|||
# Note: We are paginating through an array here but this should OK as:
|
||||
#
|
||||
# In CE, we can have a maximum group nesting depth of 21, so including
|
||||
# project cluster, we can have max 22 clusters for a group hierachy.
|
||||
# project cluster, we can have max 22 clusters for a group hierarchy.
|
||||
# In EE (Premium) we can have any number, as multiple clusters are
|
||||
# supported, but the number of clusters are fairly low currently.
|
||||
#
|
||||
|
|
|
@ -91,6 +91,7 @@ module IssuableCollections
|
|||
options = {
|
||||
scope: params[:scope],
|
||||
state: params[:state],
|
||||
confidential: Gitlab::Utils.to_boolean(params[:confidential]),
|
||||
sort: set_sort_order
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ module LfsRequest
|
|||
(authentication_abilities || []).include?(capability)
|
||||
end
|
||||
|
||||
# Overriden in EE
|
||||
# Overridden in EE
|
||||
def limit_exceeded?
|
||||
false
|
||||
end
|
||||
|
|
|
@ -134,7 +134,7 @@ class GroupDescendantsFinder
|
|||
def subgroups
|
||||
return Group.none unless Group.supports_nested_objects?
|
||||
|
||||
# When filtering subgroups, we want to find all matches withing the tree of
|
||||
# When filtering subgroups, we want to find all matches within the tree of
|
||||
# descendants to show to the user
|
||||
groups = if params[:filter]
|
||||
subgroups_matching_filter
|
||||
|
|
|
@ -69,7 +69,16 @@ class IssuesFinder < IssuableFinder
|
|||
end
|
||||
|
||||
def filter_items(items)
|
||||
by_due_date(super)
|
||||
issues = super
|
||||
issues = by_due_date(issues)
|
||||
issues = by_confidential(issues)
|
||||
issues
|
||||
end
|
||||
|
||||
def by_confidential(items)
|
||||
return items if params[:confidential].nil?
|
||||
|
||||
params[:confidential] ? items.confidential_only : items.public_only
|
||||
end
|
||||
|
||||
def by_due_date(items)
|
||||
|
|
|
@ -13,7 +13,7 @@ module CountHelper
|
|||
# memberships, and deducting 1 for each root of the fork network.
|
||||
# This might be inacurate as the root of the fork network might have been deleted.
|
||||
#
|
||||
# This makes querying this information a lot more effecient and it should be
|
||||
# This makes querying this information a lot more efficient and it should be
|
||||
# accurate enough for the instance wide statistics
|
||||
def approximate_fork_count_with_delimiters(count_data)
|
||||
fork_network_count = count_data[ForkNetwork]
|
||||
|
|
|
@ -18,7 +18,7 @@ module Ci
|
|||
FailedToPersistDataError = Class.new(StandardError)
|
||||
|
||||
# Note: The ordering of this enum is related to the precedence of persist store.
|
||||
# The bottom item takes the higest precedence, and the top item takes the lowest precedence.
|
||||
# The bottom item takes the highest precedence, and the top item takes the lowest precedence.
|
||||
enum data_store: {
|
||||
redis: 1,
|
||||
database: 2,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# it is difficult to accomplish it.
|
||||
#
|
||||
# This module defines a format to use `delete_all` and delete associated external data.
|
||||
# Here is an exmaple
|
||||
# Here is an example
|
||||
#
|
||||
# Situation
|
||||
# - `Project` has many `Ci::BuildTraceChunk` through `Ci::Build`
|
||||
|
|
|
@ -4,7 +4,7 @@ module IidRoutes
|
|||
##
|
||||
# This automagically enforces all related routes to use `iid` instead of `id`
|
||||
# If you want to use `iid` for some routes and `id` for other routes, this module should not to be included,
|
||||
# instead you should define `iid` or `id` explictly at each route generators. e.g. pipeline_path(project.id, pipeline.iid)
|
||||
# instead you should define `iid` or `id` explicitly at each route generators. e.g. pipeline_path(project.id, pipeline.iid)
|
||||
def to_param
|
||||
iid.to_s
|
||||
end
|
||||
|
|
|
@ -66,6 +66,7 @@ class Issue < ActiveRecord::Base
|
|||
scope :preload_associations, -> { preload(:labels, project: :namespace) }
|
||||
|
||||
scope :public_only, -> { where(confidential: false) }
|
||||
scope :confidential_only, -> { where(confidential: true) }
|
||||
|
||||
after_save :expire_etag_cache
|
||||
after_save :ensure_metrics, unless: :imported?
|
||||
|
|
|
@ -153,7 +153,7 @@ class NotificationRecipient
|
|||
user.global_notification_setting
|
||||
end
|
||||
|
||||
# Returns the notificaton_setting of the lowest group in hierarchy with non global level
|
||||
# Returns the notification_setting of the lowest group in hierarchy with non global level
|
||||
def closest_non_global_group_notification_settting
|
||||
return unless @group
|
||||
return if indexed_group_notification_settings.empty?
|
||||
|
|
|
@ -249,10 +249,10 @@ class Project < ActiveRecord::Base
|
|||
has_many :container_repositories, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||
|
||||
has_many :commit_statuses
|
||||
# The relation :all_pipelines is intented to be used when we want to get the
|
||||
# The relation :all_pipelines is intended to be used when we want to get the
|
||||
# whole list of pipelines associated to the project
|
||||
has_many :all_pipelines, class_name: 'Ci::Pipeline', inverse_of: :project
|
||||
# The relation :ci_pipelines is intented to be used when we want to get only
|
||||
# The relation :ci_pipelines is intended to be used when we want to get only
|
||||
# those pipeline which are directly related to CI. There are
|
||||
# other pipelines, like webide ones, that we won't retrieve
|
||||
# if we use this relation.
|
||||
|
@ -1216,7 +1216,7 @@ class Project < ActiveRecord::Base
|
|||
"#{web_url}.git"
|
||||
end
|
||||
|
||||
# Is overriden in EE
|
||||
# Is overridden in EE
|
||||
def lfs_http_url_to_repo(_)
|
||||
http_url_to_repo
|
||||
end
|
||||
|
|
|
@ -112,10 +112,10 @@ module Ci
|
|||
def extra_options(options = {})
|
||||
# In Ruby 2.4, even when options is empty, f(**options) doesn't work when f
|
||||
# doesn't have any parameters. We reproduce the Ruby 2.5 behavior by
|
||||
# checking explicitely that no arguments are given.
|
||||
# checking explicitly that no arguments are given.
|
||||
raise ArgumentError if options.any?
|
||||
|
||||
{} # overriden in EE
|
||||
{} # overridden in EE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,11 +38,11 @@ module Ci
|
|||
end
|
||||
|
||||
def create_pipeline_from_job(job)
|
||||
# overriden in EE
|
||||
# overridden in EE
|
||||
end
|
||||
|
||||
def job_from_token
|
||||
# overriden in EE
|
||||
# overridden in EE
|
||||
end
|
||||
|
||||
def variables
|
||||
|
|
|
@ -235,6 +235,6 @@ class GitPushService < BaseService
|
|||
private
|
||||
|
||||
def pipeline_options
|
||||
{} # to be overriden in EE
|
||||
{} # to be overridden in EE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,6 +61,6 @@ class GitTagPushService < BaseService
|
|||
end
|
||||
|
||||
def pipeline_options
|
||||
{} # to be overriden in EE
|
||||
{} # to be overridden in EE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ module Groups
|
|||
private
|
||||
|
||||
def after_build_hook(group, params)
|
||||
# overriden in EE
|
||||
# overridden in EE
|
||||
end
|
||||
|
||||
def create_chat_team?
|
||||
|
|
|
@ -31,7 +31,7 @@ module Groups
|
|||
private
|
||||
|
||||
def before_assignment_hook(group, params)
|
||||
# overriden in EE
|
||||
# overridden in EE
|
||||
end
|
||||
|
||||
def after_update
|
||||
|
|
|
@ -360,7 +360,7 @@ module SystemNoteService
|
|||
# author - User performing the change
|
||||
# branch_type - 'source' or 'target'
|
||||
# old_branch - old branch name
|
||||
# new_branch - new branch nmae
|
||||
# new_branch - new branch name
|
||||
#
|
||||
# Example Note text:
|
||||
#
|
||||
|
|
|
@ -128,6 +128,14 @@
|
|||
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
|
||||
%button.btn.btn-link{ type: 'button' }
|
||||
= _('No')
|
||||
#js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
|
||||
%ul.filter-dropdown{ data: { dropdown: true } }
|
||||
%li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
|
||||
%button.btn.btn-link{ type: 'button' }
|
||||
= _('Yes')
|
||||
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
|
||||
%button.btn.btn-link{ type: 'button' }
|
||||
= _('No')
|
||||
|
||||
= render_if_exists 'shared/issuable/filter_weight', type: type
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Ability to filter confidential issues
|
||||
merge_request: 24960
|
||||
author: Robert Schilling
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix 404s when C++ .gitignore template selected
|
||||
merge_request: 25416
|
||||
author:
|
||||
type: fixed
|
|
@ -32,6 +32,7 @@ GET /issues?author_id=5
|
|||
GET /issues?assignee_id=5
|
||||
GET /issues?my_reaction_emoji=star
|
||||
GET /issues?search=foo&in=title
|
||||
GET /issues?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
@ -52,6 +53,7 @@ GET /issues?search=foo&in=title
|
|||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues
|
||||
|
@ -148,6 +150,7 @@ GET /groups/:id/issues?search=issue+title+or+description
|
|||
GET /groups/:id/issues?author_id=5
|
||||
GET /groups/:id/issues?assignee_id=5
|
||||
GET /groups/:id/issues?my_reaction_emoji=star
|
||||
GET /groups/:id/issues?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
@ -168,6 +171,7 @@ GET /groups/:id/issues?my_reaction_emoji=star
|
|||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4/issues
|
||||
|
@ -264,6 +268,7 @@ GET /projects/:id/issues?search=issue+title+or+description
|
|||
GET /projects/:id/issues?author_id=5
|
||||
GET /projects/:id/issues?assignee_id=5
|
||||
GET /projects/:id/issues?my_reaction_emoji=star
|
||||
GET /projects/:id/issues?confidential=true
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
@ -284,6 +289,8 @@ GET /projects/:id/issues?my_reaction_emoji=star
|
|||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
| `confidential ` | Boolean | no | Filter confidential or public issues. |
|
||||
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues
|
||||
|
|
|
@ -54,6 +54,7 @@ module API
|
|||
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
|
||||
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
|
||||
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
|
||||
optional :confidential, type: Boolean, desc: 'Filter confidential or public issues'
|
||||
use :pagination
|
||||
|
||||
use :issues_params_ee
|
||||
|
|
|
@ -36,7 +36,10 @@ module API
|
|||
optional :project, type: String, desc: 'The project name to use when expanding placeholders in the template. Only affects licenses'
|
||||
optional :fullname, type: String, desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses'
|
||||
end
|
||||
get ':id/templates/:type/:name', requirements: { name: /[\w\.-]+/ } do
|
||||
# The regex is needed to ensure a period (e.g. agpl-3.0)
|
||||
# isn't confused with a format type. We also need to allow encoded
|
||||
# values (e.g. C%2B%2B for C++), so allow % and + as well.
|
||||
get ':id/templates/:type/:name', requirements: { name: /[\w%.+-]+/ } do
|
||||
template = TemplateFinder
|
||||
.build(params[:type], user_project, name: params[:name])
|
||||
.execute
|
||||
|
|
|
@ -112,7 +112,8 @@ describe IssuableCollections do
|
|||
assignee_username: 'user1',
|
||||
author_id: '2',
|
||||
author_username: 'user2',
|
||||
authorized_only: 'true',
|
||||
authorized_only: 'yes',
|
||||
confidential: true,
|
||||
due_date: '2017-01-01',
|
||||
group_id: '3',
|
||||
iids: '4',
|
||||
|
@ -140,6 +141,7 @@ describe IssuableCollections do
|
|||
'assignee_username' => 'user1',
|
||||
'author_id' => '2',
|
||||
'author_username' => 'user2',
|
||||
'confidential' => true,
|
||||
'label_name' => 'foo',
|
||||
'milestone_title' => 'bar',
|
||||
'my_reaction_emoji' => 'thumbsup',
|
||||
|
|
|
@ -66,7 +66,7 @@ describe 'Dropdown hint', :js do
|
|||
it 'filters with text' do
|
||||
filtered_search.set('a')
|
||||
|
||||
expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
|
||||
expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -119,6 +119,15 @@ describe 'Dropdown hint', :js do
|
|||
expect_tokens([{ name: 'my-reaction' }])
|
||||
expect_filtered_search_input_empty
|
||||
end
|
||||
|
||||
it 'opens the yes-no dropdown when you click on confidential' do
|
||||
click_hint('confidential')
|
||||
|
||||
expect(page).to have_css(js_dropdown_hint, visible: false)
|
||||
expect(page).to have_css('#js-dropdown-confidential', visible: true)
|
||||
expect_tokens([{ name: 'confidential' }])
|
||||
expect_filtered_search_input_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe 'selecting from dropdown with some input' do
|
||||
|
|
|
@ -100,7 +100,7 @@ describe 'Search bar', :js do
|
|||
find('.filtered-search-box .clear-search').click
|
||||
filtered_search.click
|
||||
|
||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
|
||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
|
||||
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -278,7 +278,7 @@ describe 'GFM autocomplete', :js do
|
|||
end
|
||||
end
|
||||
|
||||
# This context has jsut one example in each contexts in order to improve spec performance.
|
||||
# This context has just one example in each contexts in order to improve spec performance.
|
||||
context 'labels', :quarantine do
|
||||
let!(:backend) { create(:label, project: project, title: 'backend') }
|
||||
let!(:bug) { create(:label, project: project, title: 'bug') }
|
||||
|
|
|
@ -77,7 +77,7 @@ describe 'Editing file blob', :js do
|
|||
click_link 'Preview'
|
||||
wait_for_requests
|
||||
|
||||
# the above generates two seperate lists (not embedded) in CommonMark
|
||||
# the above generates two separate lists (not embedded) in CommonMark
|
||||
expect(page).to have_content("sublist")
|
||||
expect(page).not_to have_xpath("//ol//li//ul")
|
||||
end
|
||||
|
|
|
@ -170,7 +170,7 @@ describe 'Projects > Wiki > User previews markdown changes', :js do
|
|||
fill_in :wiki_content, with: "1. one\n - sublist\n"
|
||||
click_on "Preview"
|
||||
|
||||
# the above generates two seperate lists (not embedded) in CommonMark
|
||||
# the above generates two separate lists (not embedded) in CommonMark
|
||||
expect(page).to have_content("sublist")
|
||||
expect(page).not_to have_xpath("//ol//li//ul")
|
||||
end
|
||||
|
|
|
@ -490,6 +490,32 @@ describe IssuesFinder do
|
|||
end
|
||||
end
|
||||
|
||||
context 'filtering by confidential' do
|
||||
set(:confidential_issue) { create(:issue, project: project1, confidential: true) }
|
||||
|
||||
context 'no filtering' do
|
||||
it 'returns all issues' do
|
||||
expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, confidential_issue)
|
||||
end
|
||||
end
|
||||
|
||||
context 'user filters confidential issues' do
|
||||
let(:params) { { confidential: true } }
|
||||
|
||||
it 'returns only confdential issues' do
|
||||
expect(issues).to contain_exactly(confidential_issue)
|
||||
end
|
||||
end
|
||||
|
||||
context 'user filters only public issues' do
|
||||
let(:params) { { confidential: false } }
|
||||
|
||||
it 'returns only confdential issues' do
|
||||
expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is unauthorized' do
|
||||
let(:search_user) { nil }
|
||||
|
||||
|
@ -556,7 +582,7 @@ describe IssuesFinder do
|
|||
it 'returns the number of rows for the default state' do
|
||||
finder = described_class.new(user)
|
||||
|
||||
expect(finder.row_count).to eq(4)
|
||||
expect(finder.row_count).to eq(5)
|
||||
end
|
||||
|
||||
it 'returns the number of rows for a given state' do
|
||||
|
|
|
@ -765,6 +765,15 @@ describe Issue do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.confidential_only' do
|
||||
it 'only returns confidential_only issues' do
|
||||
create(:issue)
|
||||
confidential_issue = create(:issue, confidential: true)
|
||||
|
||||
expect(described_class.confidential_only).to eq([confidential_issue])
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'throttled touch' do
|
||||
subject { create(:issue, updated_at: 1.hour.ago) }
|
||||
end
|
||||
|
|
|
@ -183,6 +183,18 @@ describe API::Issues do
|
|||
expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
|
||||
end
|
||||
|
||||
it 'returns only confidential issues' do
|
||||
get api('/issues', user), params: { confidential: true, scope: 'all' }
|
||||
|
||||
expect_paginated_array_response(confidential_issue.id)
|
||||
end
|
||||
|
||||
it 'returns only public issues' do
|
||||
get api('/issues', user), params: { confidential: false }
|
||||
|
||||
expect_paginated_array_response([issue.id, closed_issue.id])
|
||||
end
|
||||
|
||||
it 'returns issues reacted by the authenticated user' do
|
||||
issue2 = create(:issue, project: project, author: user, assignees: [user])
|
||||
create(:award_emoji, awardable: issue2, user: user2, name: 'star')
|
||||
|
@ -557,6 +569,18 @@ describe API::Issues do
|
|||
expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
|
||||
end
|
||||
|
||||
it 'returns only confidential issues' do
|
||||
get api(base_url, user), params: { confidential: true }
|
||||
|
||||
expect_paginated_array_response(group_confidential_issue.id)
|
||||
end
|
||||
|
||||
it 'returns only public issues' do
|
||||
get api(base_url, user), params: { confidential: false }
|
||||
|
||||
expect_paginated_array_response([group_closed_issue.id, group_issue.id])
|
||||
end
|
||||
|
||||
it 'returns an array of labeled group issues' do
|
||||
get api(base_url, user), params: { labels: group_label.title }
|
||||
|
||||
|
@ -782,6 +806,18 @@ describe API::Issues do
|
|||
expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
|
||||
end
|
||||
|
||||
it 'returns only confidential issues' do
|
||||
get api("#{base_url}/issues", author), params: { confidential: true }
|
||||
|
||||
expect_paginated_array_response(confidential_issue.id)
|
||||
end
|
||||
|
||||
it 'returns only public issues' do
|
||||
get api("#{base_url}/issues", author), params: { confidential: false }
|
||||
|
||||
expect_paginated_array_response([issue.id, closed_issue.id])
|
||||
end
|
||||
|
||||
it 'returns project confidential issues for assignee' do
|
||||
get api("#{base_url}/issues", assignee)
|
||||
|
||||
|
|
|
@ -92,6 +92,22 @@ describe API::ProjectTemplates do
|
|||
expect(json_response['name']).to eq('Actionscript')
|
||||
end
|
||||
|
||||
it 'returns C++ gitignore' do
|
||||
get api("/projects/#{public_project.id}/templates/gitignores/C++")
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/template')
|
||||
expect(json_response['name']).to eq('C++')
|
||||
end
|
||||
|
||||
it 'returns C++ gitignore for URL-encoded names' do
|
||||
get api("/projects/#{public_project.id}/templates/gitignores/C%2B%2B")
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/template')
|
||||
expect(json_response['name']).to eq('C++')
|
||||
end
|
||||
|
||||
it 'returns a specific gitlab_ci_yml' do
|
||||
get api("/projects/#{public_project.id}/templates/gitlab_ci_ymls/Android")
|
||||
|
||||
|
@ -125,6 +141,18 @@ describe API::ProjectTemplates do
|
|||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/license')
|
||||
end
|
||||
|
||||
shared_examples 'path traversal attempt' do |template_type|
|
||||
it 'rejects invalid filenames' do
|
||||
get api("/projects/#{public_project.id}/templates/#{template_type}/%2e%2e%2fPython%2ea")
|
||||
|
||||
expect(response).to have_gitlab_http_status(500)
|
||||
end
|
||||
end
|
||||
|
||||
TemplateFinder::VENDORED_TEMPLATES.each do |template_type, _|
|
||||
it_behaves_like 'path traversal attempt', template_type
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/templates/licenses/:key' do
|
||||
|
|
Loading…
Reference in New Issue