Add latest changes from gitlab-org/gitlab@master
|
|
@ -361,18 +361,33 @@ module ApplicationSettingImplementation
|
|||
|
||||
def separate_whitelists(string_array)
|
||||
string_array.reduce([[], []]) do |(ip_whitelist, domain_whitelist), string|
|
||||
ip_obj = Gitlab::Utils.string_to_ip_object(string)
|
||||
address, port = parse_addr_and_port(string)
|
||||
|
||||
ip_obj = Gitlab::Utils.string_to_ip_object(address)
|
||||
|
||||
if ip_obj
|
||||
ip_whitelist << ip_obj
|
||||
ip_whitelist << Gitlab::UrlBlockers::IpWhitelistEntry.new(ip_obj, port: port)
|
||||
else
|
||||
domain_whitelist << string
|
||||
domain_whitelist << Gitlab::UrlBlockers::DomainWhitelistEntry.new(address, port: port)
|
||||
end
|
||||
|
||||
[ip_whitelist, domain_whitelist]
|
||||
end
|
||||
end
|
||||
|
||||
def parse_addr_and_port(str)
|
||||
case str
|
||||
when /\A\[(?<address> .* )\]:(?<port> \d+ )\z/x # string like "[::1]:80"
|
||||
address, port = $~[:address], $~[:port]
|
||||
when /\A(?<address> [^:]+ ):(?<port> \d+ )\z/x # string like "127.0.0.1:80"
|
||||
address, port = $~[:address], $~[:port]
|
||||
else # string with no port number
|
||||
address, port = str, nil
|
||||
end
|
||||
|
||||
[address, port&.to_i]
|
||||
end
|
||||
|
||||
def array_to_string(arr)
|
||||
arr&.join("\n")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Ensure that uploaded files are what they say they are for security and
|
||||
# handling purposes. The checks are not 100% reliable so we err on the side of
|
||||
# caution and allow by default, and deny when we're confident of a fail state.
|
||||
#
|
||||
# Include this concern, then call `check_upload_type` to check all
|
||||
# uploads. Attach a `mime_type` or `extensions` parameter to only check
|
||||
# specific upload types. Both parameters will be normalized to a MIME type and
|
||||
# checked against the inferred MIME type of the upload content and filename
|
||||
# extension.
|
||||
#
|
||||
# class YourUploader
|
||||
# include UploadTypeCheck::Concern
|
||||
# check_upload_type mime_types: ['image/png', /image\/jpe?g/]
|
||||
#
|
||||
# # or...
|
||||
#
|
||||
# check_upload_type extensions: ['png', 'jpg', 'jpeg']
|
||||
# end
|
||||
#
|
||||
# The mime_types parameter can accept `NilClass`, `String`, `Regexp`,
|
||||
# `Array[String, Regexp]`. This matches the CarrierWave `extension_whitelist`
|
||||
# and `content_type_whitelist` family of behavior.
|
||||
#
|
||||
# The extensions parameter can accept `NilClass`, `String`, `Array[String]`.
|
||||
module UploadTypeCheck
|
||||
module Concern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def check_upload_type(mime_types: nil, extensions: nil)
|
||||
define_method :check_upload_type_callback do |file|
|
||||
magic_file = MagicFile.new(file.to_file)
|
||||
|
||||
# Map file extensions back to mime types.
|
||||
if extensions
|
||||
mime_types = Array(mime_types) +
|
||||
Array(extensions).map { |e| MimeMagic::EXTENSIONS[e] }
|
||||
end
|
||||
|
||||
if mime_types.nil? || magic_file.matches_mime_types?(mime_types)
|
||||
check_content_matches_extension!(magic_file)
|
||||
end
|
||||
end
|
||||
before :cache, :check_upload_type_callback
|
||||
end
|
||||
end
|
||||
|
||||
def check_content_matches_extension!(magic_file)
|
||||
return if magic_file.ambiguous_type?
|
||||
|
||||
if magic_file.magic_type != magic_file.ext_type
|
||||
raise CarrierWave::IntegrityError, 'Content type does not match file extension'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Convenience class to wrap MagicMime objects.
|
||||
class MagicFile
|
||||
attr_reader :file
|
||||
|
||||
def initialize(file)
|
||||
@file = file
|
||||
end
|
||||
|
||||
def magic_type
|
||||
@magic_type ||= MimeMagic.by_magic(file)
|
||||
end
|
||||
|
||||
def ext_type
|
||||
@ext_type ||= MimeMagic.by_path(file.path)
|
||||
end
|
||||
|
||||
def magic_type_type
|
||||
magic_type&.type
|
||||
end
|
||||
|
||||
def ext_type_type
|
||||
ext_type&.type
|
||||
end
|
||||
|
||||
def matches_mime_types?(mime_types)
|
||||
Array(mime_types).any? do |mt|
|
||||
magic_type_type =~ /\A#{mt}\z/ || ext_type_type =~ /\A#{mt}\z/
|
||||
end
|
||||
end
|
||||
|
||||
# - Both types unknown or text/plain.
|
||||
# - Ambiguous magic type with text extension. Plain text file.
|
||||
# - Text magic type with ambiguous extension. TeX file missing extension.
|
||||
def ambiguous_type?
|
||||
(ext_type.to_s.blank? && magic_type.to_s.blank?) ||
|
||||
(magic_type.to_s.blank? && ext_type_type == 'text/plain') ||
|
||||
(ext_type.to_s.blank? && magic_type_type == 'text/plain')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Include snippet description as part of snippet title search (when Elasticsearch is not enabled)
|
||||
title: Include snippet description as part of snippet title search (basic search).
|
||||
merge_request: 25961
|
||||
author:
|
||||
type: added
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add ability to whitelist ports
|
||||
merge_request: 27025
|
||||
author:
|
||||
type: added
|
||||
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 43 KiB |
|
|
@ -65,7 +65,7 @@ maximum memory threshold (in bytes) for the Unicorn worker killer by
|
|||
setting the following values `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
- For GitLab **12.7** and newer:
|
||||
|
||||
|
||||
```ruby
|
||||
unicorn['worker_memory_limit_min'] = "1024 * 1 << 20"
|
||||
unicorn['worker_memory_limit_max'] = "1280 * 1 << 20"
|
||||
|
|
|
|||
|
|
@ -118,10 +118,10 @@ upload packages:
|
|||
#'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
NOTE: **Note:**
|
||||
Some build tools, like Gradle, must make `HEAD` requests to Amazon S3 to pull a dependency’s metadata. The `gitlab_rails['packages_object_store_proxy_download']` property must be set to `true`. Without this setting, GitLab won't act as a proxy to the Amazon S3 service, and will instead return the signed URL. This will cause a `HTTP 403 Forbidden` response, since Amazon S3 expects a signed URL.
|
||||
|
||||
|
||||
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
|
||||
for the changes to take effect.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Here's the script I'll use to demonstrate - it just loops forever:
|
||||
|
||||
$ cat test.rb
|
||||
$ cat test.rb
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
loop do
|
||||
|
|
@ -75,7 +75,7 @@ Thread 1 (Thread 0xb74d76c0 (LWP 1343)):
|
|||
at eval.c:5778
|
||||
#5 rb_call0 (klass=3075304600, recv=3075299660, id=9393, oid=9393, argc=1, argv=0xbf85f490, body=0xb74c85a8, flags=2)
|
||||
at eval.c:5928
|
||||
#6 0x0805e35d in rb_call (klass=3075304600, recv=3075299660, mid=9393, argc=1, argv=0xbf85f490, scope=1,
|
||||
#6 0x0805e35d in rb_call (klass=3075304600, recv=3075299660, mid=9393, argc=1, argv=0xbf85f490, scope=1,
|
||||
self=<optimized out>) at eval.c:6176
|
||||
#7 0x080651ec in rb_eval (self=3075299660, n=0xb74c4e1c) at eval.c:3521
|
||||
#8 0x0805c31c in rb_yield_0 (val=6, self=3075299660, klass=<optimized out>, flags=0, avalue=0) at eval.c:5095
|
||||
|
|
@ -139,4 +139,4 @@ A debugging session is active.
|
|||
|
||||
Quit anyway? (y or n) y
|
||||
Detaching from program: /opt/vagrant_ruby/bin/ruby, process 1343
|
||||
$
|
||||
$
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 9.8 KiB |
|
|
@ -77,11 +77,11 @@ and they will assist you with any issues you are having.
|
|||
```shell
|
||||
kubectl get cronjobs
|
||||
```
|
||||
|
||||
|
||||
When one configures [cron-based backups](https://docs.gitlab.com/charts/backup-restore/backup.html#cron-based-backup),
|
||||
you will be able to see the new schedule here. Some details about the schedules can be found
|
||||
in [Running Automated Tasks with a CronJob](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#creating-a-cron-job)
|
||||
|
||||
|
||||
## GitLab-specific Kubernetes information
|
||||
|
||||
- Minimal config that can be used to test a Kubernetes Helm chart can be found
|
||||
|
|
@ -167,7 +167,7 @@ and they will assist you with any issues you are having.
|
|||
```shell
|
||||
kubectl exec -it <task-runner-pod-name> -- /srv/gitlab/bin/rails dbconsole -p
|
||||
```
|
||||
|
||||
|
||||
- How to get info about Helm installation status:
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 292 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -149,12 +149,12 @@ import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
|
|||
|
||||
describe('my component', () => {
|
||||
let trackingSpy;
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
const vm = mountComponent(MyComponent);
|
||||
trackingSpy = mockTracking('_category_', vm.$el, spyOn);
|
||||
});
|
||||
|
||||
|
||||
it('tracks an event when toggled', () => {
|
||||
triggerEvent('a.toggle');
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 43 KiB |
|
|
@ -195,17 +195,17 @@ module Gitlab
|
|||
The [current version history](../user/project/settings/import_export.md) also displays the equivalent GitLab version
|
||||
and it is useful for knowing which versions won't be compatible between them.
|
||||
|
||||
| Exporting GitLab version | Importing GitLab version |
|
||||
| -------------------------- | -------------------------- |
|
||||
| 11.7 to current | 11.7 to current |
|
||||
| 11.1 to 11.6 | 11.1 to 11.6 |
|
||||
| 10.8 to 11.0 | 10.8 to 11.0 |
|
||||
| 10.4 to 10.7 | 10.4 to 10.7 |
|
||||
| ... | ... |
|
||||
| 8.10.3 to 8.11 | 8.10.3 to 8.11 |
|
||||
| 8.10.0 to 8.10.2 | 8.10.0 to 8.10.2 |
|
||||
| 8.9.5 to 8.9.11 | 8.9.5 to 8.9.11 |
|
||||
| 8.9.0 to 8.9.4 | 8.9.0 to 8.9.4 |
|
||||
| Exporting GitLab version | Importing GitLab version |
|
||||
| -------------------------- | -------------------------- |
|
||||
| 11.7 to current | 11.7 to current |
|
||||
| 11.1 to 11.6 | 11.1 to 11.6 |
|
||||
| 10.8 to 11.0 | 10.8 to 11.0 |
|
||||
| 10.4 to 10.7 | 10.4 to 10.7 |
|
||||
| ... | ... |
|
||||
| 8.10.3 to 8.11 | 8.10.3 to 8.11 |
|
||||
| 8.10.0 to 8.10.2 | 8.10.0 to 8.10.2 |
|
||||
| 8.9.5 to 8.9.11 | 8.9.5 to 8.9.11 |
|
||||
| 8.9.0 to 8.9.4 | 8.9.0 to 8.9.4 |
|
||||
|
||||
### When to bump the version up
|
||||
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ and where the `message` repeats the `location` field:
|
|||
It takes around 50k characters to block for 2 seconds making this a low severity issue."
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The `description` might explain how the vulnerability works or give context about the exploit.
|
||||
It should not repeat the other fields of the vulnerability object.
|
||||
In particular, the `description` should not repeat the `location` (what is affected)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Subclasses of `AbstractReferenceFilter` generally do not override `#call`; inste
|
|||
a minimum implementation of `AbstractReferenceFilter` should define:
|
||||
|
||||
- `.reference_type`: The type of domain object.
|
||||
|
||||
|
||||
This is usually a keyword, and is used to set the `data-reference-type` attribute
|
||||
on the generated link, and is an important part of the interaction with the
|
||||
corresponding `ReferenceParser` (see below).
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
<!-- Please keep the tags in alphabetical order -->
|
||||
|
||||
| Tag | Description |
|
||||
|-|-|
|
||||
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
|
||||
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify GitLab's configuration (for example, Staging). |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), will run in a separate job that only includes quarantined tests, and is allowed to fail. The test will be skipped in its regular job so that if it fails it will not hold up the pipeline. |
|
||||
|-----|-------------|
|
||||
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
|
||||
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test will also include provisioning of at least one Kubernetes cluster to test against. *This tag is often be paired with `:orchestrated`.* |
|
||||
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify GitLab's configuration (for example, Staging). |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), will run in a separate job that only includes quarantined tests, and is allowed to fail. The test will be skipped in its regular job so that if it fails it will not hold up the pipeline. |
|
||||
| `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. |
|
||||
| `:requires_admin` | The test requires an admin account. Tests with the tag are excluded when run against Canary and Production environments. |
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 39 KiB |
|
|
@ -543,7 +543,7 @@ If everything looks good, you should be able to reach GitLab in your browser.
|
|||
|
||||
### Setting up Gitaly
|
||||
|
||||
CAUTION: **Caution:** In this architecture, having a single Gitaly server creates a single point of failure. This limitation will be removed once [Gitaly HA](https://gitlab.com/groups/gitlab-org/-/epics/842) is released.
|
||||
CAUTION: **Caution:** In this architecture, having a single Gitaly server creates a single point of failure. This limitation will be removed once [Gitaly HA](https://gitlab.com/groups/gitlab-org/-/epics/842) is released.
|
||||
|
||||
Gitaly is a service that provides high-level RPC access to Git repositories.
|
||||
It should be enabled and configured on a separate EC2 instance in one of the
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ The way you install the Go indexer depends on your version of GitLab:
|
|||
|
||||
### GitLab Omnibus
|
||||
|
||||
Since GitLab 11.8 the Go indexer is included in GitLab Omnibus.
|
||||
Since GitLab 11.8 the Go indexer is included in GitLab Omnibus.
|
||||
The former Ruby-based indexer was removed in [GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/issues/6481).
|
||||
|
||||
### From source
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 7.5 KiB |
|
|
@ -21,7 +21,7 @@ You accept and agree to the following terms and conditions for Your present and
|
|||
- **Contributions:**
|
||||
|
||||
You represent that each of Your Contributions is Your original creation.
|
||||
|
||||
|
||||
Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: (named here)".
|
||||
|
||||
You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
|
|
|||
|
|
@ -71,16 +71,24 @@ use IDNA encoding.
|
|||
The whitelist can hold a maximum of 1000 entries. Each entry can be a maximum of
|
||||
255 characters.
|
||||
|
||||
You can whitelist a particular port by specifying it in the whitelist entry.
|
||||
For example `127.0.0.1:8080` will only allow connections to port 8080 on `127.0.0.1`.
|
||||
If no port is mentioned, all ports on that IP/domain are whitelisted. An IP range
|
||||
will whitelist all ports on all IPs in that range.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
example.com;gitlab.example.com
|
||||
127.0.0.1,1:0:0:0:0:0:0:1
|
||||
127.0.0.0/8 1:0:0:0:0:0:0:0/124
|
||||
[1:0:0:0:0:0:0:1]:8080
|
||||
127.0.0.1:8080
|
||||
example.com:8080
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
Wildcards (`*.example.com`) and ports (`127.0.0.1:3000`) are not currently supported.
|
||||
Wildcards (`*.example.com`) are not currently supported.
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ To purchase additional minutes for your personal namespace:
|
|||
|
||||
1. Click your avatar, then go to **Settings > Pipeline quota**.
|
||||
1. Locate the subscription card that's linked to your personal namespace on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes will be synced to your Group.
|
||||
1. To confirm the available CI minutes for your personal projects, click your avatar, then go to **Settings > Pipeline quota**.
|
||||
1. To confirm the available CI minutes for your personal projects, click your avatar, then go to **Settings > Pipeline quota**.
|
||||
The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
|
||||
|
||||
Be aware that:
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ In our example we will end up with commit `B`, that introduced bug/error. We hav
|
|||
- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state:
|
||||
|
||||
```shell
|
||||
git reset commit-B-id <file>
|
||||
git reset commit-B-id <file>
|
||||
```
|
||||
|
||||
- There is one command we also must not forget: **creating a new branch**
|
||||
|
|
@ -487,8 +487,8 @@ git filter-branch --tree-filter 'rm filename' HEAD
|
|||
Since `git filter-branch` command might be slow on big repositories, there are
|
||||
tools that can use some of Git specifics to enable faster execution of common
|
||||
tasks (which is exactly what removing sensitive information file is about).
|
||||
An alternative is the open source community-maintained tool [BFG][bfg-repo-cleaner].
|
||||
Keep in mind that these tools are faster because they do not provide the same
|
||||
An alternative is the open source community-maintained tool [BFG][bfg-repo-cleaner].
|
||||
Keep in mind that these tools are faster because they do not provide the same
|
||||
feature set as `git filter-branch` does, but focus on specific use cases.
|
||||
|
||||
## Conclusion
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 425 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 405 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 363 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 27 KiB |
|
|
@ -180,18 +180,6 @@ These are shortcuts to your last 4 visited boards.
|
|||
When you're revisiting an issue board in a project or group with multiple boards,
|
||||
GitLab will automatically load the last board you visited.
|
||||
|
||||
### Multi-select Issue Cards
|
||||
|
||||
As the name suggest, multi-select issue cards allows more than one issue card
|
||||
to be dragged and dropped across different lists. This becomes helpful while
|
||||
moving and grooming a lot of issues at once.
|
||||
|
||||
You can multi-select an issue card by pressing `CTRL` + `Left mouse click` on
|
||||
Windows or `CMD` + `Left mouse click` on MacOS. Once done, start by dragging one
|
||||
of the issue card you have selected and drop it in the new list you want.
|
||||
|
||||

|
||||
|
||||
### Configurable Issue Boards **(STARTER)**
|
||||
|
||||
> Introduced in [GitLab Starter Edition 10.2](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration).
|
||||
|
|
@ -467,6 +455,19 @@ When dragging issues between lists, different behavior occurs depending on the s
|
|||
| From label `A` list | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
|
||||
| From assignee `Alice` list | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
|
||||
|
||||
### Multi-select issue cards
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/18954) in GitLab 12.4.
|
||||
|
||||
You can select multiple issue cards, then drag the group to another position within the list, or to another list. This makes it faster to reorder many issues at once.
|
||||
|
||||
To select and move multiple cards:
|
||||
|
||||
1. Select each card with <kbd>Ctrl</kbd>+`Click` on Windows or Linux, or <kbd>Cmd</kbd>+`Click` on MacOS.
|
||||
1. Drag one of the selected cards to another position or list and all selected cards will be moved.
|
||||
|
||||

|
||||
|
||||
## Tips
|
||||
|
||||
A few things to remember:
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 10 KiB |
|
|
@ -19,7 +19,7 @@ Unfortunately, it's not so easy and that workflow won't work. Deleting files in
|
|||
a commit doesn't actually reduce the size of the repo since the earlier commits
|
||||
and blobs are still around. What you need to do is rewrite history with Git's
|
||||
[`filter-branch` option](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#The-Nuclear-Option:-filter-branch),
|
||||
or an open source community-maintained tool like the
|
||||
or an open source community-maintained tool like the
|
||||
[BFG](https://rtyley.github.io/bfg-repo-cleaner/).
|
||||
|
||||
Note that even with that method, until `git gc` runs on the GitLab side, the
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ module Gitlab
|
|||
return [uri, nil] unless address_info
|
||||
|
||||
ip_address = ip_address(address_info)
|
||||
return [uri, nil] if domain_whitelisted?(uri) || ip_whitelisted?(ip_address)
|
||||
return [uri, nil] if domain_whitelisted?(uri) || ip_whitelisted?(ip_address, port: get_port(uri))
|
||||
|
||||
protected_uri_with_hostname = enforce_uri_hostname(ip_address, uri, dns_rebind_protection)
|
||||
|
||||
|
|
@ -254,11 +254,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def domain_whitelisted?(uri)
|
||||
Gitlab::UrlBlockers::UrlWhitelist.domain_whitelisted?(uri.normalized_host)
|
||||
Gitlab::UrlBlockers::UrlWhitelist.domain_whitelisted?(uri.normalized_host, port: get_port(uri))
|
||||
end
|
||||
|
||||
def ip_whitelisted?(ip_address)
|
||||
Gitlab::UrlBlockers::UrlWhitelist.ip_whitelisted?(ip_address)
|
||||
def ip_whitelisted?(ip_address, port: nil)
|
||||
Gitlab::UrlBlockers::UrlWhitelist.ip_whitelisted?(ip_address, port: port)
|
||||
end
|
||||
|
||||
def config
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module UrlBlockers
|
||||
class DomainWhitelistEntry
|
||||
attr_reader :domain, :port
|
||||
|
||||
def initialize(domain, port: nil)
|
||||
@domain = domain
|
||||
@port = port
|
||||
end
|
||||
|
||||
def match?(requested_domain, requested_port = nil)
|
||||
return false unless domain == requested_domain
|
||||
return true if port.nil?
|
||||
|
||||
port == requested_port
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module UrlBlockers
|
||||
class IpWhitelistEntry
|
||||
attr_reader :ip, :port
|
||||
|
||||
# Argument ip should be an IPAddr object
|
||||
def initialize(ip, port: nil)
|
||||
@ip = ip
|
||||
@port = port
|
||||
end
|
||||
|
||||
def match?(requested_ip, requested_port = nil)
|
||||
return false unless ip.include?(requested_ip)
|
||||
return true if port.nil?
|
||||
|
||||
port == requested_port
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,21 +4,25 @@ module Gitlab
|
|||
module UrlBlockers
|
||||
class UrlWhitelist
|
||||
class << self
|
||||
def ip_whitelisted?(ip_string)
|
||||
def ip_whitelisted?(ip_string, port: nil)
|
||||
return false if ip_string.blank?
|
||||
|
||||
ip_whitelist, _ = outbound_local_requests_whitelist_arrays
|
||||
ip_obj = Gitlab::Utils.string_to_ip_object(ip_string)
|
||||
|
||||
ip_whitelist.any? { |ip| ip.include?(ip_obj) }
|
||||
ip_whitelist.any? do |ip_whitelist_entry|
|
||||
ip_whitelist_entry.match?(ip_obj, port)
|
||||
end
|
||||
end
|
||||
|
||||
def domain_whitelisted?(domain_string)
|
||||
def domain_whitelisted?(domain_string, port: nil)
|
||||
return false if domain_string.blank?
|
||||
|
||||
_, domain_whitelist = outbound_local_requests_whitelist_arrays
|
||||
|
||||
domain_whitelist.include?(domain_string)
|
||||
domain_whitelist.any? do |domain_whitelist_entry|
|
||||
domain_whitelist_entry.match?(domain_string, port)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -501,6 +501,18 @@ describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
|
|||
it_behaves_like 'dns rebinding checks'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with ports' do
|
||||
let(:whitelist) do
|
||||
["127.0.0.1:2000"]
|
||||
end
|
||||
|
||||
it 'allows domain with port when resolved ip has port whitelisted' do
|
||||
stub_domain_resolv("www.resolve-domain.com", '127.0.0.1') do
|
||||
expect(described_class).not_to be_blocked_url("http://www.resolve-domain.com:2000", url_blocker_attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::UrlBlockers::DomainWhitelistEntry do
|
||||
let(:domain) { 'www.example.com' }
|
||||
|
||||
describe '#initialize' do
|
||||
it 'initializes without port' do
|
||||
domain_whitelist_entry = described_class.new(domain)
|
||||
|
||||
expect(domain_whitelist_entry.domain).to eq(domain)
|
||||
expect(domain_whitelist_entry.port).to be(nil)
|
||||
end
|
||||
|
||||
it 'initializes with port' do
|
||||
port = 8080
|
||||
domain_whitelist_entry = described_class.new(domain, port: port)
|
||||
|
||||
expect(domain_whitelist_entry.domain).to eq(domain)
|
||||
expect(domain_whitelist_entry.port).to eq(port)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#match?' do
|
||||
it 'matches when domain and port are equal' do
|
||||
port = 8080
|
||||
domain_whitelist_entry = described_class.new(domain, port: port)
|
||||
|
||||
expect(domain_whitelist_entry).to be_match(domain, port)
|
||||
end
|
||||
|
||||
it 'matches any port when port is nil' do
|
||||
domain_whitelist_entry = described_class.new(domain)
|
||||
|
||||
expect(domain_whitelist_entry).to be_match(domain, 8080)
|
||||
expect(domain_whitelist_entry).to be_match(domain, 9090)
|
||||
end
|
||||
|
||||
it 'does not match when port is present but requested_port is nil' do
|
||||
domain_whitelist_entry = described_class.new(domain, port: 8080)
|
||||
|
||||
expect(domain_whitelist_entry).not_to be_match(domain, nil)
|
||||
end
|
||||
|
||||
it 'matches when port and requested_port are nil' do
|
||||
domain_whitelist_entry = described_class.new(domain)
|
||||
|
||||
expect(domain_whitelist_entry).to be_match(domain)
|
||||
end
|
||||
|
||||
it 'does not match if domain is not equal' do
|
||||
domain_whitelist_entry = described_class.new(domain)
|
||||
|
||||
expect(domain_whitelist_entry).not_to be_match('www.gitlab.com', 8080)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::UrlBlockers::IpWhitelistEntry do
|
||||
let(:ipv4) { IPAddr.new('192.168.1.1') }
|
||||
|
||||
describe '#initialize' do
|
||||
it 'initializes without port' do
|
||||
ip_whitelist_entry = described_class.new(ipv4)
|
||||
|
||||
expect(ip_whitelist_entry.ip).to eq(ipv4)
|
||||
expect(ip_whitelist_entry.port).to be(nil)
|
||||
end
|
||||
|
||||
it 'initializes with port' do
|
||||
port = 8080
|
||||
ip_whitelist_entry = described_class.new(ipv4, port: port)
|
||||
|
||||
expect(ip_whitelist_entry.ip).to eq(ipv4)
|
||||
expect(ip_whitelist_entry.port).to eq(port)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#match?' do
|
||||
it 'matches with equivalent IP and port' do
|
||||
port = 8080
|
||||
ip_whitelist_entry = described_class.new(ipv4, port: port)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv4.to_s, port)
|
||||
end
|
||||
|
||||
it 'matches any port when port is nil' do
|
||||
ip_whitelist_entry = described_class.new(ipv4)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv4.to_s, 8080)
|
||||
expect(ip_whitelist_entry).to be_match(ipv4.to_s, 9090)
|
||||
end
|
||||
|
||||
it 'does not match when port is present but requested_port is nil' do
|
||||
ip_whitelist_entry = described_class.new(ipv4, port: 8080)
|
||||
|
||||
expect(ip_whitelist_entry).not_to be_match(ipv4.to_s, nil)
|
||||
end
|
||||
|
||||
it 'matches when port and requested_port are nil' do
|
||||
ip_whitelist_entry = described_class.new(ipv4)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv4.to_s)
|
||||
end
|
||||
|
||||
it 'works with ipv6' do
|
||||
ipv6 = IPAddr.new('fe80::c800:eff:fe74:8')
|
||||
ip_whitelist_entry = described_class.new(ipv6)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv6.to_s, 8080)
|
||||
end
|
||||
|
||||
it 'matches ipv4 within IPv4 range' do
|
||||
ipv4_range = IPAddr.new('127.0.0.0/28')
|
||||
ip_whitelist_entry = described_class.new(ipv4_range)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv4_range.to_range.last.to_s, 8080)
|
||||
expect(ip_whitelist_entry).not_to be_match('127.0.1.1', 8080)
|
||||
end
|
||||
|
||||
it 'matches IPv6 within IPv6 range' do
|
||||
ipv6_range = IPAddr.new('fd84:6d02:f6d8:c89e::/124')
|
||||
ip_whitelist_entry = described_class.new(ipv6_range)
|
||||
|
||||
expect(ip_whitelist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
|
||||
expect(ip_whitelist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -13,20 +13,17 @@ describe Gitlab::UrlBlockers::UrlWhitelist do
|
|||
end
|
||||
|
||||
describe '#domain_whitelisted?' do
|
||||
let(:whitelist) do
|
||||
[
|
||||
'www.example.com',
|
||||
'example.com'
|
||||
]
|
||||
end
|
||||
let(:whitelist) { ['www.example.com', 'example.com'] }
|
||||
|
||||
it 'returns true if domains present in whitelist' do
|
||||
not_whitelisted = ['subdomain.example.com', 'example.org']
|
||||
|
||||
aggregate_failures do
|
||||
whitelist.each do |domain|
|
||||
expect(described_class).to be_domain_whitelisted(domain)
|
||||
end
|
||||
|
||||
['subdomain.example.com', 'example.org'].each do |domain|
|
||||
not_whitelisted.each do |domain|
|
||||
expect(described_class).not_to be_domain_whitelisted(domain)
|
||||
end
|
||||
end
|
||||
|
|
@ -35,6 +32,28 @@ describe Gitlab::UrlBlockers::UrlWhitelist do
|
|||
it 'returns false when domain is blank' do
|
||||
expect(described_class).not_to be_domain_whitelisted(nil)
|
||||
end
|
||||
|
||||
context 'with ports' do
|
||||
let(:whitelist) { ['example.io:3000'] }
|
||||
|
||||
it 'returns true if domain and ports present in whitelist' do
|
||||
parsed_whitelist = [['example.io', { port: 3000 }]]
|
||||
not_whitelisted = [
|
||||
'example.io',
|
||||
['example.io', { port: 3001 }]
|
||||
]
|
||||
|
||||
aggregate_failures do
|
||||
parsed_whitelist.each do |domain_and_port|
|
||||
expect(described_class).to be_domain_whitelisted(*domain_and_port)
|
||||
end
|
||||
|
||||
not_whitelisted.each do |domain_and_port|
|
||||
expect(described_class).not_to be_domain_whitelisted(*domain_and_port)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#ip_whitelisted?' do
|
||||
|
|
@ -114,5 +133,32 @@ describe Gitlab::UrlBlockers::UrlWhitelist do
|
|||
expect(described_class).not_to be_ip_whitelisted("127.0.1.15")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with ports' do
|
||||
let(:whitelist) { ['127.0.0.9:3000', '[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443'] }
|
||||
|
||||
it 'returns true if ip and ports present in whitelist' do
|
||||
parsed_whitelist = [
|
||||
['127.0.0.9', { port: 3000 }],
|
||||
['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 443 }]
|
||||
]
|
||||
not_whitelisted = [
|
||||
'127.0.0.9',
|
||||
['127.0.0.9', { port: 3001 }],
|
||||
'[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
|
||||
['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 3001 }]
|
||||
]
|
||||
|
||||
aggregate_failures do
|
||||
parsed_whitelist.each do |ip_and_port|
|
||||
expect(described_class).to be_ip_whitelisted(*ip_and_port)
|
||||
end
|
||||
|
||||
not_whitelisted.each do |ip_and_port|
|
||||
expect(described_class).not_to be_ip_whitelisted(*ip_and_port)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,37 +2,6 @@
|
|||
|
||||
# Construct an `uploader` variable that is configured to `check_upload_type`
|
||||
# with `mime_types` and `extensions`.
|
||||
RSpec.shared_context 'uploader with type check' do
|
||||
let(:uploader_class) do
|
||||
Class.new(GitlabUploader) do
|
||||
include UploadTypeCheck::Concern
|
||||
storage :file
|
||||
end
|
||||
end
|
||||
|
||||
let(:mime_types) { nil }
|
||||
let(:extensions) { nil }
|
||||
let(:uploader) do
|
||||
uploader_class.class_exec(mime_types, extensions) do |mime_types, extensions|
|
||||
check_upload_type mime_types: mime_types, extensions: extensions
|
||||
end
|
||||
uploader_class.new(build_stubbed(:user))
|
||||
end
|
||||
end
|
||||
|
||||
# This works with the UploadTypeCheck::Concern
|
||||
RSpec.shared_context 'stubbed MimeMagic mime type detection' do
|
||||
let(:mime_type) { '' }
|
||||
let(:magic_mime) { mime_type }
|
||||
let(:ext_mime) { mime_type }
|
||||
before do
|
||||
magic_mime_obj = MimeMagic.new(magic_mime)
|
||||
ext_mime_obj = MimeMagic.new(ext_mime)
|
||||
allow(MimeMagic).to receive(:by_magic).with(anything).and_return(magic_mime_obj)
|
||||
allow(MimeMagic).to receive(:by_path).with(anything).and_return(ext_mime_obj)
|
||||
end
|
||||
end
|
||||
|
||||
# @param uploader [CarrierWave::Uploader::Base] uploader with extension_whitelist method.
|
||||
RSpec.shared_context 'ignore extension whitelist check' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ RSpec.shared_examples 'application settings examples' do
|
|||
setting.outbound_local_requests_whitelist_raw = 'example.com'
|
||||
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
[], ['example.com']
|
||||
[], [an_object_having_attributes(domain: 'example.com')]
|
||||
)
|
||||
|
||||
setting.outbound_local_requests_whitelist_raw = 'gitlab.com'
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
[], ['gitlab.com']
|
||||
[], [an_object_having_attributes(domain: 'gitlab.com')]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -81,15 +81,42 @@ RSpec.shared_examples 'application settings examples' do
|
|||
context 'outbound_local_requests_whitelist_arrays' do
|
||||
it 'separates the IPs and domains' do
|
||||
setting.outbound_local_requests_whitelist = [
|
||||
'192.168.1.1', '127.0.0.0/28', 'www.example.com', 'example.com',
|
||||
'::ffff:a00:2', '1:0:0:0:0:0:0:0/124', 'subdomain.example.com'
|
||||
'192.168.1.1',
|
||||
'127.0.0.0/28',
|
||||
'::ffff:a00:2',
|
||||
'1:0:0:0:0:0:0:0/124',
|
||||
'example.com',
|
||||
'subdomain.example.com',
|
||||
'www.example.com',
|
||||
'::',
|
||||
'1::',
|
||||
'::1',
|
||||
'1:2:3:4:5::7:8',
|
||||
'[1:2:3:4:5::7:8]',
|
||||
'[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443',
|
||||
'www.example2.com:8080',
|
||||
'example.com:8080'
|
||||
]
|
||||
|
||||
ip_whitelist = [
|
||||
IPAddr.new('192.168.1.1'), IPAddr.new('127.0.0.0/8'),
|
||||
IPAddr.new('::ffff:a00:2'), IPAddr.new('1:0:0:0:0:0:0:0/124')
|
||||
an_object_having_attributes(ip: IPAddr.new('192.168.1.1')),
|
||||
an_object_having_attributes(ip: IPAddr.new('127.0.0.0/8')),
|
||||
an_object_having_attributes(ip: IPAddr.new('::ffff:a00:2')),
|
||||
an_object_having_attributes(ip: IPAddr.new('1:0:0:0:0:0:0:0/124')),
|
||||
an_object_having_attributes(ip: IPAddr.new('::')),
|
||||
an_object_having_attributes(ip: IPAddr.new('1::')),
|
||||
an_object_having_attributes(ip: IPAddr.new('::1')),
|
||||
an_object_having_attributes(ip: IPAddr.new('1:2:3:4:5::7:8')),
|
||||
an_object_having_attributes(ip: IPAddr.new('[1:2:3:4:5::7:8]')),
|
||||
an_object_having_attributes(ip: IPAddr.new('[2001:db8:85a3:8d3:1319:8a2e:370:7348]'), port: 443)
|
||||
]
|
||||
domain_whitelist = [
|
||||
an_object_having_attributes(domain: 'example.com'),
|
||||
an_object_having_attributes(domain: 'subdomain.example.com'),
|
||||
an_object_having_attributes(domain: 'www.example.com'),
|
||||
an_object_having_attributes(domain: 'www.example2.com', port: 8080),
|
||||
an_object_having_attributes(domain: 'example.com', port: 8080)
|
||||
]
|
||||
domain_whitelist = ['www.example.com', 'example.com', 'subdomain.example.com']
|
||||
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
ip_whitelist, domain_whitelist
|
||||
|
|
@ -117,7 +144,7 @@ RSpec.shared_examples 'application settings examples' do
|
|||
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
[],
|
||||
['example.com']
|
||||
[an_object_having_attributes(domain: 'example.com')]
|
||||
)
|
||||
|
||||
setting.add_to_outbound_local_requests_whitelist(
|
||||
|
|
@ -126,7 +153,7 @@ RSpec.shared_examples 'application settings examples' do
|
|||
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
[],
|
||||
['example.com', 'gitlab.com']
|
||||
[an_object_having_attributes(domain: 'example.com'), an_object_having_attributes(domain: 'gitlab.com')]
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -137,7 +164,7 @@ RSpec.shared_examples 'application settings examples' do
|
|||
|
||||
expect(setting.outbound_local_requests_whitelist).to contain_exactly('gitlab.com')
|
||||
expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
|
||||
[], ['gitlab.com']
|
||||
[], [an_object_having_attributes(domain: 'gitlab.com')]
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -26,67 +26,3 @@ shared_examples 'accepted carrierwave upload' do
|
|||
expect { uploader.cache!(fixture_file) }.to change { uploader.file }.from(nil).to(kind_of(CarrierWave::SanitizedFile))
|
||||
end
|
||||
end
|
||||
|
||||
def check_content_matches_extension!(file = double(read: nil, path: ''))
|
||||
magic_file = UploadTypeCheck::MagicFile.new(file)
|
||||
uploader.check_content_matches_extension!(magic_file)
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'upload passes content type check' do
|
||||
it 'does not raise error' do
|
||||
expect { check_content_matches_extension! }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'upload fails content type check' do
|
||||
it 'raises error' do
|
||||
expect { check_content_matches_extension! }.to raise_error(CarrierWave::IntegrityError)
|
||||
end
|
||||
end
|
||||
|
||||
def upload_type_checked_filenames(filenames)
|
||||
Array(filenames).each do |filename|
|
||||
# Feed the uploader "some" content.
|
||||
path = File.join('spec', 'fixtures', 'dk.png')
|
||||
file = File.new(path, 'r')
|
||||
# Rename the file with what we want.
|
||||
allow(file).to receive(:path).and_return(filename)
|
||||
|
||||
# Force the content type to match the extension type.
|
||||
mime_type = MimeMagic.by_path(filename)
|
||||
allow(MimeMagic).to receive(:by_magic).and_return(mime_type)
|
||||
|
||||
uploaded_file = Rack::Test::UploadedFile.new(file, original_filename: filename)
|
||||
uploader.cache!(uploaded_file)
|
||||
end
|
||||
end
|
||||
|
||||
def upload_type_checked_fixtures(upload_fixtures)
|
||||
upload_fixtures = Array(upload_fixtures)
|
||||
upload_fixtures.each do |upload_fixture|
|
||||
path = File.join('spec', 'fixtures', upload_fixture)
|
||||
uploader.cache!(fixture_file_upload(path))
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'type checked uploads' do |upload_fixtures = nil, filenames: nil|
|
||||
it 'check type' do
|
||||
upload_fixtures = Array(upload_fixtures)
|
||||
filenames = Array(filenames)
|
||||
|
||||
times = upload_fixtures.length + filenames.length
|
||||
expect(uploader).to receive(:check_content_matches_extension!).exactly(times).times
|
||||
|
||||
upload_type_checked_fixtures(upload_fixtures) unless upload_fixtures.empty?
|
||||
upload_type_checked_filenames(filenames) unless filenames.empty?
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'skipped type checked uploads' do |upload_fixtures = nil, filenames: nil|
|
||||
it 'skip type check' do
|
||||
expect(uploader).not_to receive(:check_content_matches_extension!)
|
||||
|
||||
upload_type_checked_fixtures(upload_fixtures) if upload_fixtures
|
||||
upload_type_checked_filenames(filenames) if filenames
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe UploadTypeCheck do
|
||||
include_context 'uploader with type check'
|
||||
|
||||
def upload_fixture(filename)
|
||||
fixture_file_upload(File.join('spec', 'fixtures', filename))
|
||||
end
|
||||
|
||||
describe '#check_content_matches_extension! callback using file upload' do
|
||||
context 'when extension matches contents' do
|
||||
it 'not raise error on upload' do
|
||||
expect { uploader.cache!(upload_fixture('banana_sample.gif')) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'when extension does not match contents' do
|
||||
it 'raise error' do
|
||||
expect { uploader.cache!(upload_fixture('not_a_png.png')) }.to raise_error(CarrierWave::IntegrityError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#check_content_matches_extension! callback using stubs' do
|
||||
include_context 'stubbed MimeMagic mime type detection'
|
||||
|
||||
context 'when no extension and with ambiguous/text content' do
|
||||
let(:magic_mime) { '' }
|
||||
let(:ext_mime) { '' }
|
||||
|
||||
it_behaves_like 'upload passes content type check'
|
||||
end
|
||||
|
||||
context 'when no extension and with non-text content' do
|
||||
let(:magic_mime) { 'image/gif' }
|
||||
let(:ext_mime) { '' }
|
||||
|
||||
it_behaves_like 'upload fails content type check'
|
||||
end
|
||||
|
||||
# Most text files will exhibit this behaviour.
|
||||
context 'when ambiguous content with text extension' do
|
||||
let(:magic_mime) { '' }
|
||||
let(:ext_mime) { 'text/plain' }
|
||||
|
||||
it_behaves_like 'upload passes content type check'
|
||||
end
|
||||
|
||||
context 'when text content with text extension' do
|
||||
let(:magic_mime) { 'text/plain' }
|
||||
let(:ext_mime) { 'text/plain' }
|
||||
|
||||
it_behaves_like 'upload passes content type check'
|
||||
end
|
||||
|
||||
context 'when ambiguous content with non-text extension' do
|
||||
let(:magic_mime) { '' }
|
||||
let(:ext_mime) { 'application/zip' }
|
||||
|
||||
it_behaves_like 'upload fails content type check'
|
||||
end
|
||||
|
||||
# These are the types when uploading a .dmg
|
||||
context 'when content and extension do not match' do
|
||||
let(:magic_mime) { 'application/x-bzip' }
|
||||
let(:ext_mime) { 'application/x-apple-diskimage' }
|
||||
|
||||
it_behaves_like 'upload fails content type check'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#check_content_matches_extension! mime_type filtering' do
|
||||
context 'without mime types' do
|
||||
let(:mime_types) { nil }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt rails_sample.jpg]
|
||||
end
|
||||
|
||||
context 'with mime types string' do
|
||||
let(:mime_types) { 'text/plain' }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt]
|
||||
it_behaves_like 'skipped type checked uploads', %w[dk.png]
|
||||
end
|
||||
|
||||
context 'with mime types regex' do
|
||||
let(:mime_types) { [/image\/(gif|png)/] }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[banana_sample.gif dk.png]
|
||||
it_behaves_like 'skipped type checked uploads', %w[doc_sample.txt]
|
||||
end
|
||||
|
||||
context 'with mime types array' do
|
||||
let(:mime_types) { ['text/plain', /image\/png/] }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt dk.png]
|
||||
it_behaves_like 'skipped type checked uploads', %w[audio_sample.wav]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#check_content_matches_extension! extensions filtering' do
|
||||
context 'without extensions' do
|
||||
let(:extensions) { nil }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt dk.png]
|
||||
end
|
||||
|
||||
context 'with extensions string' do
|
||||
let(:extensions) { 'txt' }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt]
|
||||
it_behaves_like 'skipped type checked uploads', %w[rails_sample.jpg]
|
||||
end
|
||||
|
||||
context 'with extensions array of strings' do
|
||||
let(:extensions) { %w[txt png] }
|
||||
|
||||
it_behaves_like 'type checked uploads', %w[doc_sample.txt dk.png]
|
||||
it_behaves_like 'skipped type checked uploads', %w[audio_sample.wav]
|
||||
end
|
||||
end
|
||||
end
|
||||