Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a683d38a36
commit
caafd2e499
49 changed files with 425 additions and 159 deletions
|
@ -37,6 +37,10 @@ export default {
|
|||
required: false,
|
||||
default: '',
|
||||
},
|
||||
mounts: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
imageRoot: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
|
@ -25,11 +25,15 @@ const createApolloProvider = appData => {
|
|||
},
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
const mounts = appData.mounts.map(mount => ({ __typename: 'Mount', ...mount }));
|
||||
|
||||
defaultClient.cache.writeData({
|
||||
data: {
|
||||
appData: {
|
||||
__typename: 'AppData',
|
||||
...appData,
|
||||
mounts,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -6,5 +6,9 @@ query appData {
|
|||
sourcePath
|
||||
username
|
||||
returnUrl
|
||||
mounts {
|
||||
source
|
||||
target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,11 @@ type SavedContentMeta {
|
|||
branch: SavedContentField!
|
||||
}
|
||||
|
||||
type Mount {
|
||||
source: String!
|
||||
target: String
|
||||
}
|
||||
|
||||
type AppData {
|
||||
isSupportedContent: Boolean!
|
||||
hasSubmittedChanges: Boolean!
|
||||
|
@ -21,6 +26,7 @@ type AppData {
|
|||
returnUrl: String
|
||||
sourcePath: String!
|
||||
username: String!
|
||||
mounts: [Mount]!
|
||||
}
|
||||
|
||||
input HasSubmittedChangesInput {
|
||||
|
|
|
@ -20,9 +20,6 @@ const initStaticSiteEditor = el => {
|
|||
imageUploadPath,
|
||||
mounts,
|
||||
} = el.dataset;
|
||||
// NOTE that the object in 'mounts' is a JSON string from the data attribute, so it must be parsed into an object.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const mountsObject = JSON.parse(mounts);
|
||||
const { current_username: username } = window.gon;
|
||||
const returnUrl = el.dataset.returnUrl || null;
|
||||
const router = createRouter(baseUrl);
|
||||
|
@ -30,6 +27,7 @@ const initStaticSiteEditor = el => {
|
|||
isSupportedContent: parseBoolean(isSupportedContent),
|
||||
hasSubmittedChanges: false,
|
||||
project: `${namespace}/${project}`,
|
||||
mounts: JSON.parse(mounts), // NOTE that the object in 'mounts' is a JSON string from the data attribute, so it must be parsed into an object.
|
||||
returnUrl,
|
||||
sourcePath,
|
||||
username,
|
||||
|
|
|
@ -138,6 +138,7 @@ export default {
|
|||
:content="sourceContent.content"
|
||||
:saving-changes="isSavingChanges"
|
||||
:return-url="appData.returnUrl"
|
||||
:mounts="appData.mounts"
|
||||
@submit="onPrepareSubmit"
|
||||
/>
|
||||
<edit-meta-modal
|
||||
|
|
5
changelogs/unreleased/257822-null-byes-in-url.yml
Normal file
5
changelogs/unreleased/257822-null-byes-in-url.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Handle malformed strings in URL
|
||||
merge_request: 45701
|
||||
author:
|
||||
type: fixed
|
|
@ -28,7 +28,7 @@ module Gitlab
|
|||
require_dependency Rails.root.join('lib/gitlab/middleware/basic_health_check')
|
||||
require_dependency Rails.root.join('lib/gitlab/middleware/same_site_cookies')
|
||||
require_dependency Rails.root.join('lib/gitlab/middleware/handle_ip_spoof_attack_error')
|
||||
require_dependency Rails.root.join('lib/gitlab/middleware/handle_null_bytes')
|
||||
require_dependency Rails.root.join('lib/gitlab/middleware/handle_malformed_strings')
|
||||
require_dependency Rails.root.join('lib/gitlab/runtime')
|
||||
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
|
@ -257,7 +257,7 @@ module Gitlab
|
|||
|
||||
config.middleware.insert_before ActionDispatch::RemoteIp, ::Gitlab::Middleware::HandleIpSpoofAttackError
|
||||
|
||||
config.middleware.use ::Gitlab::Middleware::HandleNullBytes
|
||||
config.middleware.insert_after ActionDispatch::ActionableExceptions, ::Gitlab::Middleware::HandleMalformedStrings
|
||||
|
||||
# Allow access to GitLab API from other domains
|
||||
config.middleware.insert_before Warden::Manager, Rack::Cors do
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Integrity check Rake task **(CORE ONLY)**
|
||||
|
||||
GitLab provides Rake tasks to check the integrity of various components.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Changing your time zone
|
||||
|
||||
The global time zone configuration parameter can be changed in `config/gitlab.yml`:
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Uploads administration **(CORE ONLY)**
|
||||
|
||||
Uploads represent all user data that may be sent to GitLab as a single file. As an example, avatars and notes' attachments are uploads. Uploads are integral to GitLab functionality, and therefore cannot be disabled.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Modifying global user settings
|
||||
|
||||
GitLab administrators can modify user settings for the entire GitLab instance.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Sidekiq queues administration API **(CORE ONLY)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# API resources
|
||||
|
||||
Available resources for the [GitLab API](README.md) can be grouped in the following contexts:
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Appearance API **(CORE ONLY)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16647) in GitLab 12.7.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Applications API
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8160) in GitLab 10.5.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Audit Events API
|
||||
|
||||
## Instance Audit Events **(PREMIUM ONLY)**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Avatar API
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19121) in GitLab 11.0.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Broadcast Messages API
|
||||
|
||||
> Introduced in GitLab 8.12.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Custom Attributes API
|
||||
|
||||
Every API call to custom attributes must be authenticated as administrator.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Dependencies API **(ULTIMATE)**
|
||||
|
||||
CAUTION: **Caution:**
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Dependency Proxy API **(PREMIUM)**
|
||||
|
||||
## Purge the dependency proxy for a group
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Epic Links API **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) in GitLab 11.8.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Events
|
||||
|
||||
## Filter parameters
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Geo Nodes API **(PREMIUM ONLY)**
|
||||
|
||||
To interact with Geo node endpoints, you need to authenticate yourself as an
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Set up an Audit Report with GraphQL
|
||||
|
||||
This page describes how you can use the GraphiQL explorer to set up an audit report
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Getting started with GitLab GraphQL API
|
||||
|
||||
This guide demonstrates basic usage of GitLab's GraphQL API.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# GraphQL API
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) in GitLab 11.0 (enabled by feature flag `graphql`).
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Identify issue boards with GraphQL
|
||||
|
||||
This page describes how you can use the GraphiQL explorer to identify
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Group Activity Analytics API
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) in GitLab 12.9.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Group badges API
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) in GitLab 10.6.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Group Import/Export API
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20353) in GitLab 12.8.
|
||||
|
|
|
@ -23,9 +23,9 @@ selected group. From your group page:
|
|||
To create an epic from the epic list, in a group:
|
||||
|
||||
1. Go to **{epic}** **Epics**.
|
||||
1. Click **New epic**.
|
||||
1. Select **New epic**.
|
||||
1. Enter a descriptive title.
|
||||
1. Click **Create epic**.
|
||||
1. Select **Create epic**.
|
||||
|
||||
### Access the New Epic form
|
||||
|
||||
|
@ -33,8 +33,8 @@ To create an epic from the epic list, in a group:
|
|||
|
||||
There are two ways to get to the New Epic form and create an epic in the group you're in:
|
||||
|
||||
- From an epic in your group, click **New Epic**.
|
||||
- From anywhere, in the top menu, click **plus** (**{plus-square}**) **> New epic**.
|
||||
- From an epic in your group, select **New Epic**.
|
||||
- From anywhere, in the top menu, select **plus** (**{plus-square}**) **> New epic**.
|
||||
|
||||
![New epic from an open epic](img/new_epic_from_groups_v13.2.png)
|
||||
|
||||
|
@ -63,13 +63,13 @@ After you create an epic, you can edit change the following details:
|
|||
|
||||
To edit an epic's title or description:
|
||||
|
||||
1. Click the **Edit title and description** **{pencil}** button.
|
||||
1. Select the **Edit title and description** **{pencil}** button.
|
||||
1. Make your changes.
|
||||
1. Click **Save changes**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
To edit an epics' start date, due date, or labels:
|
||||
|
||||
1. Click **Edit** next to each section in the epic sidebar.
|
||||
1. Select **Edit** next to each section in the epic sidebar.
|
||||
1. Select the dates or labels for your epic.
|
||||
|
||||
## Bulk-edit epics
|
||||
|
@ -82,7 +82,7 @@ You can edit multiple epics at once. To learn how to do it, visit
|
|||
NOTE: **Note:**
|
||||
To delete an epic, you need to be an [Owner](../../permissions.md#group-members-permissions) of a group/subgroup.
|
||||
|
||||
When editing the description of an epic, click the **Delete** button to delete the epic.
|
||||
When editing the description of an epic, select the **Delete** button to delete the epic.
|
||||
A modal appears to confirm your action.
|
||||
|
||||
Deleting an epic releases all existing issues from their associated epic in the system.
|
||||
|
@ -92,7 +92,7 @@ Deleting an epic releases all existing issues from their associated epic in the
|
|||
Whenever you decide that there is no longer need for that epic,
|
||||
close the epic by:
|
||||
|
||||
- Clicking the **Close epic** button.
|
||||
- Selecting the **Close epic** button.
|
||||
|
||||
![close epic - button](img/button_close_epic.png)
|
||||
|
||||
|
@ -129,7 +129,7 @@ that of Issues and Merge Requests) based on following parameters:
|
|||
|
||||
![epics search](img/epics_search.png)
|
||||
|
||||
To search, go to the list of epics and click the field **Search or filter results**.
|
||||
To search, go to the list of epics and select the field **Search or filter results**.
|
||||
It will display a dropdown menu, from which you can add an author. You can also enter plain
|
||||
text to search by epic title or description. When done, press <kbd>Enter</kbd> on your
|
||||
keyboard to filter the list.
|
||||
|
@ -168,7 +168,7 @@ To make an epic confidential:
|
|||
|
||||
### Add a new issue to an epic
|
||||
|
||||
You can add an existing issue to an epic, or, create a new issue that's
|
||||
You can add an existing issue to an epic, or create a new issue that's
|
||||
automatically added to the epic.
|
||||
|
||||
#### Add an existing issue to an epic
|
||||
|
@ -183,15 +183,15 @@ current parent.
|
|||
|
||||
To add a new issue to an epic:
|
||||
|
||||
1. Click the **Add** dropdown button.
|
||||
1. Click **Add a new issue**.
|
||||
1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
|
||||
1. Select **Add an existing issue**.
|
||||
1. Identify the issue to be added, using either of the following methods:
|
||||
- Paste the link of the issue.
|
||||
- Search for the desired issue by entering part of the issue's title, then selecting the desired
|
||||
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
|
||||
|
||||
If there are multiple issues to be added, press <kbd>Spacebar</kbd> and repeat this step.
|
||||
1. Click **Add**.
|
||||
1. Select **Add**.
|
||||
|
||||
#### Create an issue from an epic
|
||||
|
||||
|
@ -202,11 +202,11 @@ while dividing work into smaller parts.
|
|||
|
||||
To create an issue from an epic:
|
||||
|
||||
1. On the epic's page, under **Epics and Issues**, click the **Add** dropdown button and select
|
||||
**Create new issue**.
|
||||
1. On the epic's page, under **Epics and Issues**, select the **Add** dropdown button.
|
||||
1. Select **Add a new issue**.
|
||||
1. Under **Title**, enter the title for the new issue.
|
||||
1. From the **Project** dropdown, select the project in which the issue should be created.
|
||||
1. Click **Create issue**.
|
||||
1. Select **Create issue**.
|
||||
|
||||
### Remove an issue from an epic
|
||||
|
||||
|
@ -215,9 +215,9 @@ After you remove an issue from an epic, the issue will no longer be associated w
|
|||
|
||||
To remove an issue from an epic:
|
||||
|
||||
1. Click the **Remove** (**{close}**) button next to the issue you want to remove.
|
||||
1. Select the **Remove** (**{close}**) button next to the issue you want to remove.
|
||||
The **Remove issue** warning appears.
|
||||
1. Click **Remove**.
|
||||
1. Select **Remove**.
|
||||
|
||||
![List of issues assigned to an epic](img/issue_list_v13_1.png)
|
||||
|
||||
|
@ -285,15 +285,15 @@ For more on epic templates, see [Epic Templates - Repeatable sets of issues](htt
|
|||
|
||||
To add a child epic to an epic:
|
||||
|
||||
1. Click the **Add** dropdown button.
|
||||
1. Click **Add a new epic**.
|
||||
1. Select the **Add** dropdown button.
|
||||
1. Select **Add a new epic**.
|
||||
1. Identify the epic to be added, using either of the following methods:
|
||||
- Paste the link of the epic.
|
||||
- Search for the desired issue by entering part of the epic's title, then selecting the desired
|
||||
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
|
||||
|
||||
If there are multiple epics to be added, press <kbd>Spacebar</kbd> and repeat this step.
|
||||
1. Click **Add**.
|
||||
1. Select **Add**.
|
||||
|
||||
### Move child epics between epics
|
||||
|
||||
|
@ -325,5 +325,5 @@ To reorder child epics assigned to an epic:
|
|||
|
||||
To remove a child epic from a parent epic:
|
||||
|
||||
1. Click on the <kbd>x</kbd> button in the parent epic's list of epics.
|
||||
1. Click **Remove** in the **Remove epic** warning message.
|
||||
1. Select the <kbd>x</kbd> button in the parent epic's list of epics.
|
||||
1. Select **Remove** in the **Remove epic** warning message.
|
||||
|
|
|
@ -25,7 +25,8 @@ module API
|
|||
Gitlab::GrapeLogging::Loggers::QueueDurationLogger.new,
|
||||
Gitlab::GrapeLogging::Loggers::PerfLogger.new,
|
||||
Gitlab::GrapeLogging::Loggers::CorrelationIdLogger.new,
|
||||
Gitlab::GrapeLogging::Loggers::ContextLogger.new
|
||||
Gitlab::GrapeLogging::Loggers::ContextLogger.new,
|
||||
Gitlab::GrapeLogging::Loggers::ContentLogger.new
|
||||
]
|
||||
|
||||
allow_access_with_scope :api
|
||||
|
|
|
@ -134,6 +134,7 @@ mobsf-android-sast:
|
|||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
|
||||
MOBSF_API_KEY: key
|
||||
rules:
|
||||
- if: $SAST_DISABLED
|
||||
when: never
|
||||
|
@ -152,6 +153,7 @@ mobsf-ios-sast:
|
|||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
|
||||
MOBSF_API_KEY: key
|
||||
rules:
|
||||
- if: $SAST_DISABLED
|
||||
when: never
|
||||
|
|
|
@ -54,7 +54,13 @@ module Gitlab
|
|||
|
||||
add_instrument_for_cache_hit(status_code, route, request)
|
||||
|
||||
[status_code, { 'ETag' => etag, 'X-Gitlab-From-Cache' => 'true' }, []]
|
||||
new_headers = {
|
||||
'ETag' => etag,
|
||||
'X-Gitlab-From-Cache' => 'true',
|
||||
::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => route.feature_category
|
||||
}
|
||||
|
||||
[status_code, new_headers, []]
|
||||
end
|
||||
|
||||
def track_cache_miss(if_none_match, cached_value_present, route)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
module Gitlab
|
||||
module EtagCaching
|
||||
class Router
|
||||
Route = Struct.new(:regexp, :name)
|
||||
Route = Struct.new(:regexp, :name, :feature_category)
|
||||
# We enable an ETag for every request matching the regex.
|
||||
# To match a regex the path needs to match the following:
|
||||
# - Don't contain a reserved word (expect for the words used in the
|
||||
|
@ -20,59 +20,73 @@ module Gitlab
|
|||
ROUTES = [
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/noteable/issue/\d+/notes\z),
|
||||
'issue_notes'
|
||||
'issue_notes',
|
||||
'issue_tracking'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/noteable/merge_request/\d+/notes\z),
|
||||
'merge_request_notes'
|
||||
'merge_request_notes',
|
||||
'code_review'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/issues/\d+/realtime_changes\z),
|
||||
'issue_title'
|
||||
'issue_title',
|
||||
'issue_tracking'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/commit/\S+/pipelines\.json\z),
|
||||
'commit_pipelines'
|
||||
'commit_pipelines',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/new\.json\z),
|
||||
'new_merge_request_pipelines'
|
||||
'new_merge_request_pipelines',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/\d+/pipelines\.json\z),
|
||||
'merge_request_pipelines'
|
||||
'merge_request_pipelines',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/pipelines\.json\z),
|
||||
'project_pipelines'
|
||||
'project_pipelines',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/pipelines/\d+\.json\z),
|
||||
'project_pipeline'
|
||||
'project_pipeline',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/builds/\d+\.json\z),
|
||||
'project_build'
|
||||
'project_build',
|
||||
'continuous_integration'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/clusters/\d+/environments\z),
|
||||
'cluster_environments'
|
||||
'cluster_environments',
|
||||
'continuous_delivery'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/environments\.json\z),
|
||||
'environments'
|
||||
'environments',
|
||||
'continuous_delivery'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/import/github/realtime_changes\.json\z),
|
||||
'realtime_changes_import_github'
|
||||
'realtime_changes_import_github',
|
||||
'importers'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/import/gitea/realtime_changes\.json\z),
|
||||
'realtime_changes_import_gitea'
|
||||
'realtime_changes_import_gitea',
|
||||
'importers'
|
||||
),
|
||||
Gitlab::EtagCaching::Router::Route.new(
|
||||
%r(#{RESERVED_WORDS_PREFIX}/merge_requests/\d+/cached_widget\.json\z),
|
||||
'merge_request_widget'
|
||||
'merge_request_widget',
|
||||
'code_review'
|
||||
)
|
||||
].freeze
|
||||
|
||||
|
|
16
lib/gitlab/grape_logging/loggers/content_logger.rb
Normal file
16
lib/gitlab/grape_logging/loggers/content_logger.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module GrapeLogging
|
||||
module Loggers
|
||||
class ContentLogger < ::GrapeLogging::Loggers::Base
|
||||
def parameters(request, _)
|
||||
{
|
||||
content_length: request.env['CONTENT_LENGTH'],
|
||||
content_range: request.env['HTTP_CONTENT_RANGE']
|
||||
}.compact
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
module Gitlab
|
||||
module Middleware
|
||||
# There is no valid reason for a request to contain a null byte (U+0000)
|
||||
# There is no valid reason for a request to contain a malformed string
|
||||
# so just return HTTP 400 (Bad Request) if we receive one
|
||||
class HandleNullBytes
|
||||
class HandleMalformedStrings
|
||||
NULL_BYTE_REGEX = Regexp.new(Regexp.escape("\u0000")).freeze
|
||||
|
||||
attr_reader :app
|
||||
|
@ -14,18 +14,20 @@ module Gitlab
|
|||
end
|
||||
|
||||
def call(env)
|
||||
return [400, {}, ["Bad Request"]] if request_has_null_byte?(env)
|
||||
return [400, { 'Content-Type' => 'text/plain' }, ['Bad Request']] if request_contains_malformed_string?(env)
|
||||
|
||||
app.call(env)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request_has_null_byte?(request)
|
||||
return false if ENV['REJECT_NULL_BYTES'] == "1"
|
||||
def request_contains_malformed_string?(request)
|
||||
return false if ENV['DISABLE_REQUEST_VALIDATION'] == '1'
|
||||
|
||||
request = Rack::Request.new(request)
|
||||
|
||||
return true if string_malformed?(request.path)
|
||||
|
||||
request.params.values.any? do |value|
|
||||
param_has_null_byte?(value)
|
||||
end
|
||||
|
@ -39,7 +41,7 @@ module Gitlab
|
|||
depth += 1
|
||||
|
||||
if value.respond_to?(:match)
|
||||
string_contains_null_byte?(value)
|
||||
string_malformed?(value)
|
||||
elsif value.respond_to?(:values)
|
||||
value.values.any? do |hash_value|
|
||||
param_has_null_byte?(hash_value, depth)
|
||||
|
@ -53,8 +55,11 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def string_contains_null_byte?(string)
|
||||
def string_malformed?(string)
|
||||
string.match?(NULL_BYTE_REGEX)
|
||||
rescue ArgumentError
|
||||
# If we're here, we caught a malformed string. Return true
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -304,7 +304,7 @@ RSpec.describe 'User comments on a diff', :js do
|
|||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'suggestion is presented' do
|
||||
it 'suggestion is presented', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/268240' do
|
||||
page.within('.diff-discussions') do
|
||||
expect(page).to have_button('Apply suggestion')
|
||||
expect(page).to have_content('Suggested change')
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
sourceContentHeaderObjYAML as headerSettings,
|
||||
sourceContentBody as body,
|
||||
returnUrl,
|
||||
mounts,
|
||||
} from '../mock_data';
|
||||
|
||||
jest.mock('~/static_site_editor/services/formatter', () => jest.fn(str => `${str} format-pass`));
|
||||
|
@ -31,6 +32,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
|
|||
title,
|
||||
content,
|
||||
returnUrl,
|
||||
mounts,
|
||||
savingChanges,
|
||||
...propsData,
|
||||
},
|
||||
|
|
|
@ -67,3 +67,10 @@ export const images = new Map([
|
|||
['path/to/image1.png', 'image1-content'],
|
||||
['path/to/image2.png', 'image2-content'],
|
||||
]);
|
||||
|
||||
export const mounts = [
|
||||
{
|
||||
source: 'some/source/',
|
||||
target: '',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
submitChangesError,
|
||||
trackingCategory,
|
||||
images,
|
||||
mounts,
|
||||
} from '../mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
|
@ -41,6 +42,7 @@ describe('static_site_editor/pages/home', () => {
|
|||
project,
|
||||
username,
|
||||
sourcePath,
|
||||
mounts,
|
||||
};
|
||||
const hasSubmittedChangesMutationPayload = {
|
||||
data: {
|
||||
|
@ -119,6 +121,7 @@ describe('static_site_editor/pages/home', () => {
|
|||
it('provides source content, returnUrl, and isSavingChanges to the edit area', () => {
|
||||
expect(findEditArea().props()).toMatchObject({
|
||||
title,
|
||||
mounts,
|
||||
content,
|
||||
returnUrl,
|
||||
savingChanges: false,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::EtagCaching::Middleware do
|
||||
RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state do
|
||||
let(:app) { double(:app) }
|
||||
let(:middleware) { described_class.new(app) }
|
||||
let(:app_status_code) { 200 }
|
||||
|
@ -17,10 +17,12 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
|
|||
mock_app_response
|
||||
end
|
||||
|
||||
it 'does not add ETag header' do
|
||||
it 'does not add ETag headers' do
|
||||
_, headers, _ = middleware.call(build_request(path, if_none_match))
|
||||
|
||||
expect(headers['ETag']).to be_nil
|
||||
expect(headers['X-Gitlab-From-Cache']).to be_nil
|
||||
expect(headers[::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER]).to be_nil
|
||||
end
|
||||
|
||||
it 'passes status code from app' do
|
||||
|
@ -68,7 +70,7 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
|
|||
mock_value_in_store('123')
|
||||
end
|
||||
|
||||
it 'returns this value as header' do
|
||||
it 'returns the correct headers' do
|
||||
_, headers, _ = middleware.call(build_request(path, if_none_match))
|
||||
|
||||
expect(headers['ETag']).to eq 'W/"123"'
|
||||
|
@ -126,6 +128,13 @@ RSpec.describe Gitlab::EtagCaching::Middleware do
|
|||
expect(status).to eq 304
|
||||
end
|
||||
|
||||
it 'sets correct headers' do
|
||||
_, headers, _ = middleware.call(build_request(path, if_none_match))
|
||||
|
||||
expect(headers).to include('X-Gitlab-From-Cache' => 'true',
|
||||
::Gitlab::Metrics::RequestsRackMiddleware::FEATURE_CATEGORY_HEADER => 'issue_tracking')
|
||||
end
|
||||
|
||||
it_behaves_like 'sends a process_action.action_controller notification', 304
|
||||
|
||||
it 'returns empty body' do
|
||||
|
|
|
@ -127,4 +127,12 @@ RSpec.describe Gitlab::EtagCaching::Router do
|
|||
expect(result).to be_present
|
||||
expect(result.name).to eq 'project_pipeline'
|
||||
end
|
||||
|
||||
it 'has a valid feature category for every route', :aggregate_failures do
|
||||
feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).to_set
|
||||
|
||||
described_class::ROUTES.each do |route|
|
||||
expect(feature_categories).to include(route.feature_category), "#{route.name} has a category of #{route.feature_category}, which is not valid"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
109
spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
Normal file
109
spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb
Normal file
|
@ -0,0 +1,109 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require "rack/test"
|
||||
|
||||
RSpec.describe Gitlab::Middleware::HandleMalformedStrings do
|
||||
let(:null_byte) { "\u0000" }
|
||||
let(:invalid_string) { "mal\xC0formed" }
|
||||
let(:error_400) { [400, { 'Content-Type' => 'text/plain' }, ['Bad Request']] }
|
||||
let(:app) { double(:app) }
|
||||
|
||||
subject { described_class.new(app) }
|
||||
|
||||
before do
|
||||
allow(app).to receive(:call) do |args|
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
def env_for(params = {})
|
||||
Rack::MockRequest.env_for('/', { params: params })
|
||||
end
|
||||
|
||||
context 'in the URL' do
|
||||
it 'rejects null bytes' do
|
||||
# We have to create the env separately or Rack::MockRequest complains about invalid URI
|
||||
env = env_for
|
||||
env['PATH_INFO'] = "/someplace/witha#{null_byte}nullbyte"
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it 'rejects malformed strings' do
|
||||
# We have to create the env separately or Rack::MockRequest complains about invalid URI
|
||||
env = env_for
|
||||
env['PATH_INFO'] = "/someplace/with_an/#{invalid_string}"
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
end
|
||||
|
||||
context 'in params' do
|
||||
shared_examples_for 'checks params' do
|
||||
it 'rejects bad params in a top level param' do
|
||||
env = env_for(name: "null#{problematic_input}byte")
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "rejects bad params for hashes with strings" do
|
||||
env = env_for(name: { inner_key: "I am #{problematic_input} bad" })
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "rejects bad params for arrays with strings" do
|
||||
env = env_for(name: ["I am #{problematic_input} bad"])
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "rejects bad params for arrays containing hashes with string values" do
|
||||
env = env_for(name: [
|
||||
{
|
||||
inner_key: "I am #{problematic_input} bad"
|
||||
}
|
||||
])
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "gives up and does not reject too deeply nested params" do
|
||||
env = env_for(name: [
|
||||
{
|
||||
inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{problematic_input} bad" }] }
|
||||
}
|
||||
])
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
|
||||
context 'with null byte' do
|
||||
it_behaves_like 'checks params' do
|
||||
let(:problematic_input) { null_byte }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with malformed strings' do
|
||||
it_behaves_like 'checks params' do
|
||||
let(:problematic_input) { invalid_string }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without problematic input' do
|
||||
it "does not error for strings" do
|
||||
env = env_for(name: "safe name")
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
|
||||
it "does not error with no params" do
|
||||
env = env_for
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,88 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require "rack/test"
|
||||
|
||||
RSpec.describe Gitlab::Middleware::HandleNullBytes do
|
||||
let(:null_byte) { "\u0000" }
|
||||
let(:error_400) { [400, {}, ["Bad Request"]] }
|
||||
let(:app) { double(:app) }
|
||||
|
||||
subject { described_class.new(app) }
|
||||
|
||||
before do
|
||||
allow(app).to receive(:call) do |args|
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
def env_for(params = {})
|
||||
Rack::MockRequest.env_for('/', { params: params })
|
||||
end
|
||||
|
||||
context 'with null bytes in params' do
|
||||
it 'rejects null bytes in a top level param' do
|
||||
env = env_for(name: "null#{null_byte}byte")
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "responds with 400 BadRequest for hashes with strings" do
|
||||
env = env_for(name: { inner_key: "I am #{null_byte} bad" })
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "responds with 400 BadRequest for arrays with strings" do
|
||||
env = env_for(name: ["I am #{null_byte} bad"])
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "responds with 400 BadRequest for arrays containing hashes with string values" do
|
||||
env = env_for(name: [
|
||||
{
|
||||
inner_key: "I am #{null_byte} bad"
|
||||
}
|
||||
])
|
||||
|
||||
expect(subject.call(env)).to eq error_400
|
||||
end
|
||||
|
||||
it "gives up and does not 400 with too deeply nested params" do
|
||||
env = env_for(name: [
|
||||
{
|
||||
inner_key: { deeper_key: [{ hash_inside_array_key: "I am #{null_byte} bad" }] }
|
||||
}
|
||||
])
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
|
||||
context 'without null bytes in params' do
|
||||
it "does not respond with a 400 for strings" do
|
||||
env = env_for(name: "safe name")
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
|
||||
it "does not respond with a 400 with no params" do
|
||||
env = env_for
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
|
||||
context 'when disabled via env flag' do
|
||||
before do
|
||||
stub_env('REJECT_NULL_BYTES', '1')
|
||||
end
|
||||
|
||||
it 'does not respond with a 400 no matter what' do
|
||||
env = env_for(name: "null#{null_byte}byte")
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
end
|
20
spec/requests/user_sends_malformed_strings_spec.rb
Normal file
20
spec/requests/user_sends_malformed_strings_spec.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'User sends malformed strings as params' do
|
||||
let(:null_byte) { "\u0000" }
|
||||
let(:invalid_string) { "mal\xC0formed" }
|
||||
|
||||
it 'raises a 400 error with a null byte' do
|
||||
post '/nonexistent', params: { a: "A #{null_byte} nasty string" }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
|
||||
it 'raises a 400 error with an invalid string' do
|
||||
post '/nonexistent', params: { a: "A #{invalid_string} nasty string" }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'User sends null bytes as params' do
|
||||
let(:null_byte) { "\u0000" }
|
||||
|
||||
it 'raises a 400 error' do
|
||||
post '/nonexistent', params: { a: "A #{null_byte} nasty string" }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
expect(response.body).to eq('Bad Request')
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue