Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-04 15:09:27 +00:00
parent 433ee53e3e
commit aca89cb7e9
38 changed files with 702 additions and 236 deletions

View File

@ -1 +1 @@
a6091637dcb4c3b601a8860b5f164c0ce90ba0ca
d02d473234dc18649e5a359ee203d6a3aa5c4031

View File

@ -328,6 +328,7 @@ class ProjectPolicy < BasePolicy
enable :move_design
enable :destroy_design
enable :read_terraform_state
enable :read_pod_logs
end
rule { can?(:developer_access) & user_confirmed? }.policy do
@ -367,7 +368,6 @@ class ProjectPolicy < BasePolicy
enable :admin_operations
enable :read_deploy_token
enable :create_deploy_token
enable :read_pod_logs
enable :destroy_deploy_token
enable :read_prometheus_alerts
enable :admin_terraform_state

View File

@ -37,6 +37,7 @@
= render 'groups/settings/default_branch_protection', f: f, group: @group
= render 'groups/settings/project_creation_level', f: f, group: @group
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
= render_if_exists 'groups/settings/prevent_forking', f: f, group: @group
= render 'groups/settings/two_factor_auth', f: f
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
= render_if_exists 'groups/member_lock_setting', f: f, group: @group

View File

@ -10,6 +10,7 @@ module ApplicationWorker
include Sidekiq::Worker # rubocop:disable Cop/IncludeSidekiqWorker
include WorkerAttributes
include WorkerContext
include Gitlab::SidekiqVersioning::Worker
LOGGING_EXTRA_KEY = 'extra'

View File

@ -0,0 +1,5 @@
---
title: Add Prevent forking outside group feature
merge_request: 36848
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: "Add NuGet lock files support to Dependency Scanning CI template"
merge_request: 37553
author:
type: added

View File

@ -0,0 +1,6 @@
---
title: Allow users with developer access level for given project to view kubernetes
pod logs
merge_request: 38467
author:
type: changed

View File

@ -0,0 +1,7 @@
---
name: sidekiq_versioning
introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232934
group: group::fulfillment
type: development
default_enabled: false

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddPreventForkingToNamespaceSettings < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :namespace_settings, :prevent_forking_outside_group, :boolean, null: false, default: false
end
end

View File

@ -0,0 +1 @@
dbb84d05cfe6d2ef143b9321b2b089c66d705f01ced64756032622f64f8e3eed

View File

@ -13257,7 +13257,8 @@ CREATE TABLE public.namespace_root_storage_statistics (
CREATE TABLE public.namespace_settings (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
namespace_id integer NOT NULL
namespace_id integer NOT NULL,
prevent_forking_outside_group boolean DEFAULT false NOT NULL
);
CREATE TABLE public.namespace_statistics (

View File

@ -750,6 +750,7 @@ PUT /groups/:id
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
| `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
| `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces
NOTE: **Note:**
The `projects` and `shared_projects` attributes in the response are deprecated and will be [removed in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).

View File

@ -219,10 +219,30 @@ For example, to add support for files referenced by a `Widget` model with a
def carrierwave_uploader
model_record.file
end
# Change this to `true` to release replication of this model. Then remove
# this override in the next release.
# The feature flag follows the format `geo_#{replicable_name}_replication`,
# so here it would be `geo_widget_replication`
def self.replication_enabled_by_default?
false
end
end
end
```
1. Add this replicator class to the method `replicator_classes` in
`ee/lib/gitlab/geo.rb`:
```ruby
def self.replicator_classes
classes = [::Geo::PackageFileReplicator,
::Geo::WidgetReplicator]
classes.select(&:enabled?)
end
```
1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
the setup necessary to define the `model_record` variable for the shared
examples.
@ -239,13 +259,15 @@ For example, to add support for files referenced by a `Widget` model with a
end
```
1. Create the `widget_registry` table so Geo secondaries can track the sync and
1. Create the `widget_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
verification state of each Widget's file. This migration belongs in `ee/db/geo/migrate`:
```ruby
# frozen_string_literal: true
class CreateWidgetRegistry < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
@ -257,12 +279,12 @@ For example, to add support for files referenced by a `Widget` model with a
t.integer :widget_id, null: false
t.integer :state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2
t.text :last_sync_failure
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :created_at, null: false
t.text :last_sync_failure
t.index :widget_id
t.index :widget_id, name: :index_widget_registry_on_widget_id
t.index :retry_at
t.index :state
end
@ -358,8 +380,13 @@ Widgets should now be replicated by Geo!
#### Verification
1. Add verification state fields to the `widgets` table so the Geo primary can
track verification state:
There are two ways to add verification related fields so that the Geo primary
can track verification state:
##### Option 1: Add verification state fields to the existing `widgets` table itself
1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
for verification state to the widgets table:
```ruby
# frozen_string_literal: true
@ -382,7 +409,7 @@ Widgets should now be replicated by Geo!
end
```
Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
1. Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
setting a limit:
```ruby
@ -400,7 +427,7 @@ Widgets should now be replicated by Geo!
```
1. Add a partial index on `verification_failure` and `verification_checksum` to ensure
re-verification can be performed efficiently:
re-verification can be performed efficiently. Add a migration in `ee/db/geo/migrate/`:
```ruby
# frozen_string_literal: true
@ -424,6 +451,65 @@ Widgets should now be replicated by Geo!
end
```
##### Option 2: Create a separate `widget_states` table with verification state fields
1. Add a migration in `ee/db/geo/migrate/` to create a `widget_states` table and add a
partial index on `verification_failure` and `verification_checksum` to ensure
re-verification can be performed efficiently. Order the columns according to [our guidelines](../ordering_table_columns.md):
```ruby
# frozen_string_literal: true
class CreateWidgetStates < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:widget_states)
with_lock_retries do
create_table :widget_states, id: false do |t|
t.references :widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
t.datetime_with_timezone :verification_retry_at
t.datetime_with_timezone :verified_at
t.integer :verification_retry_count, limit: 2
t.binary :verification_checksum, using: 'verification_checksum::bytea'
t.text :verification_failure
t.index :verification_failure, where: "(verification_failure IS NOT NULL)", name: "widgets_verification_failure_partial"
t.index :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "widgets_verification_checksum_partial"
end
end
end
add_text_limit :widget_states, :verification_failure, 255
end
def down
drop_table :widget_states
end
end
```
1. Add the following lines to the `widget` model:
```ruby
class Widget < ApplicationRecord
...
has_one :widget_state, inverse_of: :widget
delegate :verification_retry_at, :verification_retry_at=,
:verified_at, :verified_at=,
:verification_checksum, :verification_checksum=,
:verification_failure, :verification_failure=,
:verification_retry_count, :verification_retry_count=,
to: :widget_state
...
end
```
To do: Add verification on secondaries. This should be done as part of
[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)

View File

@ -64,6 +64,36 @@ the extra jobs will take resources away from jobs from workers that were already
there, if the resources available to the Sidekiq process handling the namespace
are not adjusted appropriately.
## Versioning
Version can be specified on each Sidekiq worker class.
This is then sent along when the job is created.
```ruby
class FooWorker
include ApplicationWorker
version 2
def perform(*args)
if job_version == 2
foo = args.first['foo']
else
foo = args.first
end
end
end
```
Under this schema, any worker is expected to be able to handle any job that was
enqueued by an older version of that worker. This means that when changing the
arguments a worker takes, you must increment the `version` (or set `version 1`
if this is the first time a worker's arguments are changing), but also make sure
that the worker is still able to handle jobs that were queued with any earlier
version of the arguments. From the worker's `perform` method, you can read
`self.job_version` if you want to specifically branch on job version, or you
can read the number or type of provided arguments.
## Idempotent Jobs
It's known that a job can fail for multiple reasons. For example, network outages or bugs.

View File

@ -668,6 +668,23 @@ To enable delayed deletion of projects:
1. Expand the **Permissions, LFS, 2FA** section, and check **Enable delayed project removal**.
1. Click **Save changes**.
#### Prevent project forking outside group **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
By default, projects within a group can be forked.
Optionally, on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
you can prevent the projects within a group from being forked outside of the current top-level group.
Previously this setting was available only for groups enforcing group managed account. This setting will be
removed from SAML setting page and migrated to group setting, but in the interim period of changes both of those settings will be taken into consideration, if even one is set to `true` then it will be assumed group does not allow forking projects outside.
To enable prevent project forking:
1. Navigate to the top-level group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section, and check **Prevent project forking outside current group**.
1. Click **Save changes**.
### Advanced settings
- **Projects**: View all projects within that group, add members to each project,

View File

@ -142,7 +142,7 @@ The following table depicts the various user permission levels in a project.
| Remove GitLab Pages | | | | ✓ | ✓ |
| Manage clusters | | | | ✓ | ✓ |
| Manage Project Operations | | | | ✓ | ✓ |
| View Pods logs | | | | ✓ | ✓ |
| View Pods logs | | | | ✓ | ✓ |
| Read Terraform state | | | ✓ | ✓ | ✓ |
| Manage Terraform state | | | | ✓ | ✓ |
| Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ |

View File

@ -3,6 +3,9 @@ stage: Create
group: Source Code
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
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
stage: Create
group: Source Code
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
---
# Repository mirroring
@ -124,7 +127,87 @@ To set up a mirror from GitLab to GitHub, you need to follow these steps:
The mirrored repository will be listed. For example, `https://*****:*****@github.com/<your_github_group>/<your_github_project>.git`.
The repository will push soon. To force a push, click the appropriate button.
The repository will push soon. To force a push, click the **Update now** (**{retry}**) button.
## Setting up a push mirror from GitLab to AWS CodeCommit
AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab is not yet supported as one of their Source Code Management (SCM) providers.
Each new AWS Codepipeline needs significant AWS infrastructure setup. It also requires an individual pipeline per branch.
If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage GitLab CI/CD pipelines and simply use the AWS CLI in the final job in `.gitlab-ci.yml` to deploy to CodeDeploy.
NOTE: **Note:**
GitLab-to-AWS-CodeCommit push mirroring cannot use SSH authentication until [GitLab issue 34014](https://gitlab.com/gitlab-org/gitlab/-/issues/34014) is resolved.
To set up a mirror from GitLab to AWS CodeCommit:
1. In the AWS IAM console, create an IAM user.
1. Add the following least privileges permissions for repository mirroring as an "inline policy".
The Amazon Resource Names (ARNs) must explicitly include the region and account. The IAM policy
below grants privilege for mirroring access to two sample repositories. These permissions have
been tested to be the minimum (least privileged) required for mirroring:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "MinimumGitLabPushMirroringPermissions",
"Effect": "Allow",
"Action": [
"codecommit:GitPull",
"codecommit:GitPush"
],
"Resource": [
"arn:aws:codecommit:us-east-1:111111111111:MyDestinationRepo",
"arn:aws:codecommit:us-east-1:111111111111:MyDemo*"
]
}
]
}
```json
1. After the user was created, click the AWS IAM user name.
1. Click the **Security credentials** tab.
1. Under **HTTPS Git credentials for AWS CodeCommit** click **Generate credentials**.
NOTE: **Note:**
This Git user ID and password is specific to communicating with CodeCommit. Do
not confuse it with the IAM user ID or AWS keys of this user.
1. Copy or download special Git HTTPS user ID and password.
1. In the AWS CodeCommit console, create a new repository to mirror from your GitLab repo.
1. Open your new repository and click **Clone URL > Clone HTTPS** (not **Clone HTTPS (GRC)**).
1. In GitLab, open the repository to be push-mirrored.
1. Click **Settings > Repository** and expand **Mirroring repositories**.
1. Fill in the **Git repository URL** field using this format:
```plaintext
https://<your_aws_git_userid>@git-codecommit.<aws-region>.amazonaws.com/v1/repos/<your_codecommit_repo>
```
Replace `<your_aws_git_userid>` with the AWS **special HTTPS Git user ID** from the IAM Git
credentials created earlier. Replace `<your_codecommit_repo>` with the name of your repo in CodeCommit.
1. For **Mirror direction**, select **Push**.
1. For **Authentication method**, select **Password** and fill in the **Password** field with the special IAM Git clone user ID **password** created earlier in AWS.
1. The option **Only mirror protected branches** should be good for CodeCommit as it pushes more
frequently (from every five minutes to every minute).
CodePipeline requires individual pipeline setups for named branches you wish to have a AWS CI setup for. Since feature branches that have dynamic names will not be supported anyway, configuring **Only mirror protected branches** does not cause flexibility problems with CodePipeline integration as long as you are also willing to protect all the named branches you want to build CodePipelines for.
1. Click **Mirror repository**. You should see the mirrored repository appear:
```plaintext
https://*****:*****@git-codecommit.<aws-region>.amazonaws.com/v1/repos/<your_codecommit_repo>
```
To test mirroring by forcing a push, click the half-circle arrows button (hover text is **Update now**).
If **Last successful update** shows a date, you have configured mirroring correctly.
If it is not working correctly a red `error` tag appears and shows the error message as hover text.
## Setting up a push mirror to another GitLab instance with 2FA activated

View File

@ -111,6 +111,7 @@ gemnasium-dependency_scanning:
- '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
- '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
gemnasium-maven-dependency_scanning:
extends: .ds-analyzer

View File

@ -136,7 +136,7 @@ module Gitlab
end
def graphql_query?
request.post? && request.path.start_with?(GRAPHQL_URL)
request.post? && request.path.start_with?(File.join(relative_url, GRAPHQL_URL))
end
end
end

View File

@ -22,7 +22,7 @@ module Gitlab
keys = keys.map { |key| cache_key(key) }
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
unlink_or_delete(redis, keys)
redis.unlink(*keys)
end
end
end
@ -60,17 +60,5 @@ module Gitlab
def with(&blk)
Gitlab::Redis::Cache.with(&blk) # rubocop:disable CodeReuse/ActiveRecord
end
def unlink_or_delete(redis, keys)
if Feature.enabled?(:repository_set_cache_unlink, default_enabled: true)
redis.unlink(*keys)
else
redis.del(*keys)
end
rescue ::Redis::CommandError => e
Gitlab::ErrorTracking.log_exception(e)
redis.del(*keys)
end
end
end

View File

@ -19,6 +19,7 @@ module Gitlab
chain.add ::Labkit::Middleware::Sidekiq::Server
chain.add ::Gitlab::SidekiqMiddleware::InstrumentationLogger
chain.add ::Gitlab::SidekiqMiddleware::AdminMode::Server
chain.add ::Gitlab::SidekiqVersioning::Middleware
chain.add ::Gitlab::SidekiqStatus::ServerMiddleware
chain.add ::Gitlab::SidekiqMiddleware::WorkerContext::Server
chain.add ::Gitlab::SidekiqMiddleware::DuplicateJobs::Server

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
module Gitlab
module SidekiqVersioning
class Middleware
def call(worker, job, queue)
worker.job_version = job['version'] if worker.is_a?(ApplicationWorker) && Feature.enabled?(:sidekiq_versioning)
yield
end
end
end
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Gitlab
module SidekiqVersioning
module Worker
extend ActiveSupport::Concern
included do
version 0
attr_writer :job_version
end
class_methods do
def version(new_version = nil)
if new_version
sidekiq_options version: new_version.to_i
else
get_sidekiq_options['version']
end
end
end
# Version is not set if `new.perform` is called directly,
# and in that case we fallback to latest version
def job_version
@job_version ||= self.class.version
end
end
end
end

View File

@ -51,7 +51,7 @@ module Gitlab
def topology_app_requests_per_hour(client)
result = query_safely('gitlab_usage_ping:ops:rate5m', 'app_requests', fallback: nil) do |query|
client.query(one_week_average(query)).first
client.query(aggregate_one_week(query)).first
end
return unless result
@ -84,14 +84,14 @@ module Gitlab
end
def topology_node_memory(client)
query_safely('gitlab_usage_ping:node_memory_total_bytes:avg', 'node_memory', fallback: {}) do |query|
aggregate_by_instance(client, one_week_average(query))
query_safely('gitlab_usage_ping:node_memory_total_bytes:max', 'node_memory', fallback: {}) do |query|
aggregate_by_instance(client, aggregate_one_week(query, aggregation: :max))
end
end
def topology_node_cpus(client)
query_safely('gitlab_usage_ping:node_cpus:count', 'node_cpus', fallback: {}) do |query|
aggregate_by_instance(client, one_week_average(query, aggregation: :max))
aggregate_by_instance(client, aggregate_one_week(query, aggregation: :max))
end
end
@ -114,25 +114,25 @@ module Gitlab
def topology_service_memory_rss(client)
query_safely(
'gitlab_usage_ping:node_service_process_resident_memory_bytes:avg', 'service_rss', fallback: {}
) { |query| aggregate_by_labels(client, one_week_average(query)) }
) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_service_memory_uss(client)
query_safely(
'gitlab_usage_ping:node_service_process_unique_memory_bytes:avg', 'service_uss', fallback: {}
) { |query| aggregate_by_labels(client, one_week_average(query)) }
) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_service_memory_pss(client)
query_safely(
'gitlab_usage_ping:node_service_process_proportional_memory_bytes:avg', 'service_pss', fallback: {}
) { |query| aggregate_by_labels(client, one_week_average(query)) }
) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_all_service_process_count(client)
query_safely(
'gitlab_usage_ping:node_service_process:count', 'service_process_count', fallback: {}
) { |query| aggregate_by_labels(client, one_week_average(query)) }
) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_all_service_server_types(client)
@ -231,7 +231,7 @@ module Gitlab
end
end
def one_week_average(query, aggregation: :avg)
def aggregate_one_week(query, aggregation: :avg)
"#{aggregation}_over_time (#{query}[1w])"
end

View File

@ -10336,6 +10336,9 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
msgid "FeatureFlags|New list"
msgstr ""
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
@ -12019,6 +12022,12 @@ msgstr ""
msgid "GroupSettings|Please choose a group URL with no special characters."
msgstr ""
msgid "GroupSettings|Prevent forking outside of the group"
msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
@ -12055,6 +12064,9 @@ msgstr ""
msgid "GroupSettings|This setting will prevent group members from being notified if the group is mentioned."
msgstr ""
msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
msgstr ""
msgid "GroupSettings|Transfer group"
msgstr ""
@ -17935,6 +17947,9 @@ msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr ""
msgid "Prevent project forking outside current group"
msgstr ""
msgid "Prevent users from changing their profile name"
msgstr ""
@ -26211,9 +26226,6 @@ msgstr ""
msgid "User List"
msgstr ""
msgid "User Lists can only be created and modified with %{linkStart}the API%{linkEnd}"
msgstr ""
msgid "User OAuth applications"
msgstr ""
@ -26283,6 +26295,9 @@ msgstr ""
msgid "UserLists|Define a set of users to be used within feature flag strategies"
msgstr ""
msgid "UserLists|Edit"
msgstr ""
msgid "UserLists|Edit %{name}"
msgstr ""

View File

@ -161,7 +161,7 @@
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
"@gitlab/eslint-plugin": "3.1.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "^1.0.0-beta.30",
"@vue/test-utils": "1.0.0-beta.30",
"acorn": "^6.3.0",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^24.1.0",
@ -211,7 +211,7 @@
"stylelint-config-recommended": "^2.2.0",
"stylelint-scss": "^3.9.2",
"timezone-mock": "^1.0.8",
"vue-jest": "^4.0.0-beta.2",
"vue-jest": "4.0.0-beta.2",
"webpack-dev-server": "^3.10.3",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",

View File

@ -22,8 +22,8 @@ RSpec.describe Projects::LogsController do
describe 'GET #index' do
let(:empty_project) { create(:project) }
it 'returns 404 with developer access' do
project.add_developer(user)
it 'returns 404 with reporter access' do
project.add_reporter(user)
get :index, params: environment_params
@ -31,7 +31,7 @@ RSpec.describe Projects::LogsController do
end
it 'renders empty logs page if no environment exists' do
empty_project.add_maintainer(user)
empty_project.add_developer(user)
get :index, params: { namespace_id: empty_project.namespace, project_id: empty_project }
@ -40,7 +40,7 @@ RSpec.describe Projects::LogsController do
end
it 'renders index template' do
project.add_maintainer(user)
project.add_developer(user)
get :index, params: environment_params
@ -69,14 +69,27 @@ RSpec.describe Projects::LogsController do
end
end
it 'returns 404 with developer access' do
project.add_developer(user)
it 'returns 404 with reporter access' do
project.add_reporter(user)
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
context 'with developer access' do
before do
project.add_developer(user)
end
it 'returns the service result' do
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:success)
expect(json_response).to eq(service_result_json)
end
end
context 'with maintainer access' do
before do
project.add_maintainer(user)

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
factory :namespace_settings, class: 'NamespaceSetting' do
namespace
end
end

View File

@ -30,6 +30,10 @@ FactoryBot.define do
association :root_storage_statistics, factory: :namespace_root_storage_statistics
end
trait :with_namespace_settings do
association :namespace_settings, factory: :namespace_settings
end
# Construct a hierarchy underneath the namespace.
# Each namespace will have `children` amount of children,
# and `depth` levels of descendants.

View File

@ -110,6 +110,19 @@ RSpec.describe Gitlab::Middleware::ReadOnly do
expect(subject).not_to disallow_request
end
context 'relative URL is configured' do
before do
stub_config_setting(relative_url_root: '/gitlab')
end
it 'expects a graphql request to be allowed' do
response = request.post("/gitlab/api/graphql")
expect(response).not_to be_redirect
expect(subject).not_to disallow_request
end
end
context 'sidekiq admin requests' do
where(:mounted_at) do
[

View File

@ -93,23 +93,6 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
it { is_expected.to eq(0) }
end
context "unlink isn't supported" do
before do
allow_any_instance_of(Redis).to receive(:unlink) { raise ::Redis::CommandError }
end
it 'still deletes the given key' do
expect(cache.expire(:foo)).to eq(1)
expect(cache.read(:foo)).to be_empty
end
it 'logs the failure' do
expect(Gitlab::ErrorTracking).to receive(:log_exception)
cache.expire(:foo)
end
end
end
describe '#exist?' do

View File

@ -51,6 +51,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
Gitlab::SidekiqMiddleware::BatchLoader,
Labkit::Middleware::Sidekiq::Server,
Gitlab::SidekiqMiddleware::InstrumentationLogger,
Gitlab::SidekiqVersioning::Middleware,
Gitlab::SidekiqStatus::ServerMiddleware,
Gitlab::SidekiqMiddleware::ServerMetrics,
Gitlab::SidekiqMiddleware::ArgumentsLogger,
@ -78,6 +79,41 @@ RSpec.describe Gitlab::SidekiqMiddleware do
end
end
shared_examples "a server middleware chain for mailer" do
let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
let(:job_args) do
[
{
"job_class" => "ActionMailer::MailDeliveryJob",
"job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e",
"provider_job_id" => nil,
"queue_name" => "mailers",
"priority" => nil,
"arguments" => [
"Notify",
"test_email",
"deliver_now",
{
"args" => [
"test@example.com",
"subject",
"body"
],
"_aj_symbol_keys" => ["args"]
}
],
"executions" => 0,
"exception_executions" => {},
"locale" => "en",
"timezone" => "UTC",
"enqueued_at" => "2020-07-27T07:43:31Z"
}
]
end
it_behaves_like "a server middleware chain"
end
context "all optional middlewares off" do
let(:metrics) { false }
let(:arguments_logger) { false }
@ -91,6 +127,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
end
it_behaves_like "a server middleware chain"
it_behaves_like "a server middleware chain for mailer"
end
context "all optional middlewares on" do
@ -100,6 +137,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
let(:disabled_sidekiq_middlewares) { [] }
it_behaves_like "a server middleware chain"
it_behaves_like "a server middleware chain for mailer"
context "server metrics" do
let(:gitaly_histogram) { double(:gitaly_histogram) }

View File

@ -0,0 +1,60 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::SidekiqVersioning::Middleware do
let(:worker_class) do
Class.new do
def self.name
'DummyWorker'
end
include ApplicationWorker
version 2
end
end
describe '#call' do
let(:worker) { worker_class.new }
let(:job) { { 'version' => 3, 'queue' => queue } }
let(:queue) { worker_class.queue }
def call!(&block)
block ||= -> {}
subject.call(worker, job, queue, &block)
end
it 'sets worker.job_version' do
call!
expect(worker.job_version).to eq(job['version'])
end
it 'yields' do
expect { |b| call!(&b) }.to yield_control
end
context 'when worker is not ApplicationWorker' do
let(:worker_class) do
ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper
end
it 'does not err' do
expect { call! }.not_to raise_error
end
end
context 'when sidekiq_versioning is disabled' do
before do
stub_feature_flags(sidekiq_versioning: false)
end
it 'does not set job_version' do
expect(worker).not_to receive(:job_version=)
call!
end
end
end
end

View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::SidekiqVersioning::Worker do
let(:worker) do
Class.new do
def self.name
'DummyWorker'
end
# ApplicationWorker includes Gitlab::SidekiqVersioning::Worker
include ApplicationWorker
version 2
end
end
describe '.version' do
context 'when called with an argument' do
it 'sets the version option' do
worker.version 3
expect(worker.get_sidekiq_options['version']).to eq(3)
end
end
context 'when called without an argument' do
it 'returns the version option' do
worker.sidekiq_options version: 3
expect(worker.version).to eq(3)
end
end
end
describe '#job_version' do
let(:job) { worker.new }
context 'when job_version is not set' do
it 'returns latest version' do
expect(job.job_version).to eq(2)
end
end
context 'when job_version is set' do
it 'returns the set version' do
job.job_version = 0
expect(job.job_version).to eq(0)
end
end
end
end

View File

@ -46,7 +46,7 @@ RSpec.describe ProjectPolicy do
resolve_note create_container_image update_container_image destroy_container_image daily_statistics
create_environment update_environment create_deployment update_deployment create_release update_release
create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation
read_terraform_state
read_terraform_state read_pod_logs
]
end

View File

@ -17,49 +17,47 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package versions' | :success
'PUBLIC' | :guest | true | true | 'PyPi package versions' | :success
'PUBLIC' | :developer | true | false | 'PyPi package versions' | :success
'PUBLIC' | :guest | true | false | 'PyPi package versions' | :success
'PUBLIC' | :developer | false | true | 'PyPi package versions' | :success
'PUBLIC' | :guest | false | true | 'PyPi package versions' | :success
'PUBLIC' | :developer | false | false | 'PyPi package versions' | :success
'PUBLIC' | :guest | false | false | 'PyPi package versions' | :success
'PUBLIC' | :anonymous | false | true | 'PyPi package versions' | :success
'PRIVATE' | :developer | true | true | 'PyPi package versions' | :success
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package versions' | :success
'PUBLIC' | :guest | true | true | 'PyPi package versions' | :success
'PUBLIC' | :developer | true | false | 'PyPi package versions' | :success
'PUBLIC' | :guest | true | false | 'PyPi package versions' | :success
'PUBLIC' | :developer | false | true | 'PyPi package versions' | :success
'PUBLIC' | :guest | false | true | 'PyPi package versions' | :success
'PUBLIC' | :developer | false | false | 'PyPi package versions' | :success
'PUBLIC' | :guest | false | false | 'PyPi package versions' | :success
'PUBLIC' | :anonymous | false | true | 'PyPi package versions' | :success
'PRIVATE' | :developer | true | true | 'PyPi package versions' | :success
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
it_behaves_like 'deploy token for package GET requests'
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
it_behaves_like 'rejects PyPI access with unknown project id'
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package GET requests'
it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do
@ -70,48 +68,46 @@ RSpec.describe API::PypiPackages do
subject { post api(url), headers: headers }
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process PyPi api request' | :success
'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process PyPi api request' | :success
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process PyPi api request' | :success
'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process PyPi api request' | :success
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
it_behaves_like 'deploy token for package uploads'
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
it_behaves_like 'rejects PyPI access with unknown project id'
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'POST /api/v4/projects/:id/packages/pypi' do
@ -135,61 +131,59 @@ RSpec.describe API::PypiPackages do
)
end
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package creation' | :created
'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process PyPi api request' | :created
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package creation' | :created
'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process PyPi api request' | :created
'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
context 'with an invalid package' do
let(:token) { personal_access_token.token }
let(:user_headers) { build_basic_auth_header(user.username, token) }
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
before do
params[:name] = '.$/@!^*'
project.add_developer(user)
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like 'returning response status', :bad_request
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
context 'with an invalid package' do
let(:token) { personal_access_token.token }
let(:user_headers) { build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
before do
params[:name] = '.$/@!^*'
project.add_developer(user)
end
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'rejects PyPI access with unknown project id'
it_behaves_like 'returning response status', :bad_request
end
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do
@ -200,60 +194,58 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
context 'without the need for a license' do
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package download' | :success
'PUBLIC' | :guest | true | true | 'PyPi package download' | :success
'PUBLIC' | :developer | true | false | 'PyPi package download' | :success
'PUBLIC' | :guest | true | false | 'PyPi package download' | :success
'PUBLIC' | :developer | false | true | 'PyPi package download' | :success
'PUBLIC' | :guest | false | true | 'PyPi package download' | :success
'PUBLIC' | :developer | false | false | 'PyPi package download' | :success
'PUBLIC' | :guest | false | false | 'PyPi package download' | :success
'PUBLIC' | :anonymous | false | true | 'PyPi package download' | :success
'PRIVATE' | :developer | true | true | 'PyPi package download' | :success
'PRIVATE' | :guest | true | true | 'PyPi package download' | :success
'PRIVATE' | :developer | true | false | 'PyPi package download' | :success
'PRIVATE' | :guest | true | false | 'PyPi package download' | :success
'PRIVATE' | :developer | false | true | 'PyPi package download' | :success
'PRIVATE' | :guest | false | true | 'PyPi package download' | :success
'PRIVATE' | :developer | false | false | 'PyPi package download' | :success
'PRIVATE' | :guest | false | false | 'PyPi package download' | :success
'PRIVATE' | :anonymous | false | true | 'PyPi package download' | :success
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPi package download' | :success
'PUBLIC' | :guest | true | true | 'PyPi package download' | :success
'PUBLIC' | :developer | true | false | 'PyPi package download' | :success
'PUBLIC' | :guest | true | false | 'PyPi package download' | :success
'PUBLIC' | :developer | false | true | 'PyPi package download' | :success
'PUBLIC' | :guest | false | true | 'PyPi package download' | :success
'PUBLIC' | :developer | false | false | 'PyPi package download' | :success
'PUBLIC' | :guest | false | false | 'PyPi package download' | :success
'PUBLIC' | :anonymous | false | true | 'PyPi package download' | :success
'PRIVATE' | :developer | true | true | 'PyPi package download' | :success
'PRIVATE' | :guest | true | true | 'PyPi package download' | :success
'PRIVATE' | :developer | true | false | 'PyPi package download' | :success
'PRIVATE' | :guest | true | false | 'PyPi package download' | :success
'PRIVATE' | :developer | false | true | 'PyPi package download' | :success
'PRIVATE' | :guest | false | true | 'PyPi package download' | :success
'PRIVATE' | :developer | false | false | 'PyPi package download' | :success
'PRIVATE' | :guest | false | false | 'PyPi package download' | :success
'PRIVATE' | :anonymous | false | true | 'PyPi package download' | :success
end
context 'with deploy token headers' do
let(:headers) { build_basic_auth_header(deploy_token.username, deploy_token.token) }
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
context 'valid token' do
it_behaves_like 'returning response status', :success
subject { get api(url), headers: headers }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
context 'invalid token' do
let(:headers) { build_basic_auth_header('foo', 'bar') }
it_behaves_like 'returning response status', :success
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
it_behaves_like 'rejects PyPI access with unknown project id'
end
context 'with deploy token headers' do
let(:headers) { build_basic_auth_header(deploy_token.username, deploy_token.token) }
context 'valid token' do
it_behaves_like 'returning response status', :success
end
context 'invalid token' do
let(:headers) { build_basic_auth_header('foo', 'bar') }
it_behaves_like 'returning response status', :success
end
end
it_behaves_like 'rejects PyPI access with unknown project id'
end
end

View File

@ -83,9 +83,9 @@ RSpec.describe EnvironmentEntity do
end
context 'pod_logs' do
context 'with developer access' do
context 'with reporter access' do
before do
project.add_developer(user)
project.add_reporter(user)
end
it 'does not expose logs keys' do
@ -95,9 +95,9 @@ RSpec.describe EnvironmentEntity do
end
end
context 'with maintainer access' do
context 'with developer access' do
before do
project.add_maintainer(user)
project.add_developer(user)
end
it 'exposes logs keys' do

View File

@ -1385,7 +1385,7 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
"@vue/test-utils@^1.0.0-beta.30":
"@vue/test-utils@1.0.0-beta.30":
version "1.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.30.tgz#d5f26d1e2411fdb7fa7fdedb61b4b4ea4194c49d"
integrity sha512-Wyvcha9fNk8+kzTDwb3xWGjPkCPzHSYSwKP6MplrPTG/auhqoad7JqUEceZLc6u7AU4km2pPQ8/m9s0RgCZ0NA==
@ -12161,7 +12161,7 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
integrity sha512-2j/t+wIbyVMP5NvctQoSUvLkYKoWAAk2QlQiilrM2a6/ulzFgdcLUJfTvs4XQ/3eZhHiBmmEojbjmM4AzZj8JA==
vue-jest@^4.0.0-beta.2:
vue-jest@4.0.0-beta.2:
version "4.0.0-beta.2"
resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-4.0.0-beta.2.tgz#f2120ea9d24224aad3a100c2010b0760d47ee6fe"
integrity sha512-SywBIciuIfqsCb8Eb9UQ02s06+NV8Ry8KnbyhAfnvnyFFulIuh7ujtga9eJYq720nCS4Hz4TpVtS4pD1ZbUILQ==