Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-09-20 09:10:52 +00:00
parent b2362c5f21
commit a7b422860c
53 changed files with 921 additions and 378 deletions

View file

@ -4,25 +4,6 @@ Layout/FirstArrayElementIndentation:
Exclude:
- 'lib/gitlab/email/message/in_product_marketing/trial.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_group_level_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/nuget/nuget_project_level_spec.rb'
- 'qa/qa/specs/features/ee/api/1_manage/user/minimal_access_user_spec.rb'
- 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/advanced_global_advanced_syntax_search_spec.rb'
- 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/elasticsearch_api_spec.rb'
- 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/index_tests/main_index/blob_index_spec.rb'
- 'qa/qa/specs/features/ee/api/9_enablement/elasticsearch/nightly_elasticsearch_test_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/code_owners_with_protected_branch_and_squashed_commits_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/new_discussion_not_dropping_merge_trains_mr_spec.rb'
- 'spec/controllers/concerns/send_file_upload_spec.rb'
- 'spec/graphql/types/packages/tag_type_spec.rb'
- 'spec/helpers/application_settings_helper_spec.rb'

View file

@ -1,5 +1,6 @@
import { flatten, isString } from 'lodash';
import { languages } from 'monaco-editor';
import { setDiagnosticsOptions as yamlDiagnosticsOptions } from 'monaco-yaml';
import { performanceMarkAndMeasure } from '~/performance/utils';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
@ -82,17 +83,16 @@ export function registerLanguages(def, ...defs) {
}
export function registerSchema(schema, options = {}) {
const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
defaults.forEach((d) =>
d.setDiagnosticsOptions({
validate: true,
enableSchemaRequest: true,
hover: true,
completion: true,
schemas: [schema],
...options,
}),
);
const defaultOptions = {
validate: true,
enableSchemaRequest: true,
hover: true,
completion: true,
schemas: [schema],
...options,
};
languages.json.jsonDefaults.setDiagnosticsOptions(defaultOptions);
yamlDiagnosticsOptions(defaultOptions);
}
export const otherSide = (side) => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);

View file

@ -10,7 +10,7 @@ import {
import { createAlert } from '~/flash';
import { s__, sprintf } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import branchesQuery from '../queries/branches.query.graphql';
import branchesQuery from '../../queries/branches.query.graphql';
export const i18n = {
fetchBranchesError: s__('BranchRules|An error occurred while fetching branches.'),

View file

@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import RuleEdit from './components/rule_edit.vue';
import RuleEdit from './components/edit/index.vue';
export default function mountBranchRules(el) {
if (!el) {

View file

@ -18,6 +18,12 @@ class PersonalAccessTokensFinder
tokens = by_impersonation(tokens)
tokens = by_state(tokens)
tokens = by_owner_type(tokens)
tokens = by_revoked_state(tokens)
tokens = by_created_before(tokens)
tokens = by_created_after(tokens)
tokens = by_last_used_before(tokens)
tokens = by_last_used_after(tokens)
tokens = by_search(tokens)
sort(tokens)
end
@ -83,4 +89,40 @@ class PersonalAccessTokensFinder
tokens
end
end
def by_revoked_state(tokens)
return tokens unless params.has_key?(:revoked)
params[:revoked] ? tokens.revoked : tokens.not_revoked
end
def by_created_before(tokens)
return tokens unless params[:created_before]
tokens.created_before(params[:created_before])
end
def by_created_after(tokens)
return tokens unless params[:created_after]
tokens.created_after(params[:created_after])
end
def by_last_used_before(tokens)
return tokens unless params[:last_used_before]
tokens.last_used_before(params[:last_used_before])
end
def by_last_used_after(tokens)
return tokens unless params[:last_used_after]
tokens.last_used_after(params[:last_used_after])
end
def by_search(tokens)
return tokens unless params[:search]
tokens.search(params[:search])
end
end

View file

@ -5,6 +5,8 @@ class PersonalAccessToken < ApplicationRecord
include TokenAuthenticatable
include Sortable
include EachBatch
include CreatedAtFilterable
include Gitlab::SQL::Pattern
extend ::Gitlab::Utils::Override
add_authentication_token_field :token, digest: true
@ -24,7 +26,6 @@ class PersonalAccessToken < ApplicationRecord
scope :expiring_and_not_notified, ->(date) { where(["revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= ?", date]) }
scope :expired_today_and_not_notified, -> { where(["revoked = false AND expires_at = CURRENT_DATE AND after_expiry_notification_delivered = false"]) }
scope :inactive, -> { where("revoked = true OR expires_at < CURRENT_DATE") }
scope :created_before, -> (date) { where("personal_access_tokens.created_at < :date", date: date) }
scope :last_used_before_or_unused, -> (date) { where("personal_access_tokens.created_at < :date AND (last_used_at < :date OR last_used_at IS NULL)", date: date) }
scope :with_impersonation, -> { where(impersonation: true) }
scope :without_impersonation, -> { where(impersonation: false) }
@ -38,6 +39,8 @@ class PersonalAccessToken < ApplicationRecord
scope :order_expires_at_asc_id_desc, -> { reorder(expires_at: :asc, id: :desc) }
scope :project_access_token, -> { includes(:user).where(user: { user_type: :project_bot }) }
scope :owner_is_human, -> { includes(:user).where(user: { user_type: :human }) }
scope :last_used_before, -> (date) { where("last_used_at <= ?", date) }
scope :last_used_after, -> (date) { where("last_used_at >= ?", date) }
validates :scopes, presence: true
validate :validate_scopes
@ -90,6 +93,10 @@ class PersonalAccessToken < ApplicationRecord
Gitlab::CurrentSettings.current_application_settings.personal_access_token_prefix
end
def self.search(query)
fuzzy_search(query, [:name])
end
override :format_token
def format_token(token)
"#{self.class.token_prefix}#{token}"

View file

@ -21,7 +21,8 @@ module Preloaders
ActiveRecord::Associations::Preloader.new.preload(@projects, :namespace)
@projects.each do |project|
project.namespace.root_ancestor = root_ancestors_by_id[project.id]&.first
root_ancestor = root_ancestors_by_id[project.id]&.first
project.namespace.root_ancestor = root_ancestor if root_ancestor.present?
end
end

View file

@ -20,13 +20,13 @@ const webpack = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const { StatsWriterPlugin } = require('webpack-stats-plugin');
const WEBPACK_VERSION = require('webpack/package.json').version;
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const createIncrementalWebpackCompiler = require('./helpers/incremental_webpack_compiler');
const IS_EE = require('./helpers/is_ee_env');
const IS_JH = require('./helpers/is_jh_env');
const vendorDllHash = require('./helpers/vendor_dll_hash');
const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
const GraphqlKnownOperationsPlugin = require('./plugins/graphql_known_operations_plugin');
const ROOT_PATH = path.resolve(__dirname, '..');
@ -250,6 +250,20 @@ if (VENDOR_DLL && !IS_PRODUCTION) {
};
}
const defaultJsOptions = {
cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
cacheIdentifier: [
process.env.BABEL_ENV || process.env.NODE_ENV || 'development',
webpack.version,
BABEL_VERSION,
BABEL_LOADER_VERSION,
// Ensure that changing supported browsers will refresh the cache
// in order to not pull in outdated files that import core-js
SUPPORTED_BROWSERS_HASH,
].join('|'),
cacheCompression: false,
};
module.exports = {
mode: IS_PRODUCTION ? 'production' : 'development',
@ -285,18 +299,18 @@ module.exports = {
exclude: (modulePath) =>
/node_modules|vendor[\\/]assets/.test(modulePath) && !/\.vue\.js/.test(modulePath),
loader: 'babel-loader',
options: defaultJsOptions,
},
{
test: /\.js$/,
include: (modulePath) =>
/node_modules\/(monaco-worker-manager|monaco-marker-data-provider)\/index\.js/.test(
modulePath,
) || /node_modules\/yaml/.test(modulePath),
loader: 'babel-loader',
options: {
cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
cacheIdentifier: [
process.env.BABEL_ENV || process.env.NODE_ENV || 'development',
webpack.version,
BABEL_VERSION,
BABEL_LOADER_VERSION,
// Ensure that changing supported browsers will refresh the cache
// in order to not pull in outdated files that import core-js
SUPPORTED_BROWSERS_HASH,
].join('|'),
cacheCompression: false,
plugins: ['@babel/plugin-proposal-numeric-separator'],
...defaultJsOptions,
},
},
{
@ -492,6 +506,16 @@ module.exports = {
// automatically configure monaco editor web workers
new MonacoWebpackPlugin({
filename: '[name].[contenthash:8].worker.js',
customLanguages: [
{
label: 'yaml',
entry: 'monaco-yaml',
worker: {
id: 'monaco-yaml/yamlWorker',
entry: 'monaco-yaml/yaml.worker',
},
},
],
}),
new GraphqlKnownOperationsPlugin({ filename: 'graphql_known_operations.yml' }),

View file

@ -271,3 +271,11 @@ By default, `sudo` does not preserve existing environment variables. You should
```shell
sudo gitlab-rake gitlab:external_diffs:force_object_storage START_ID=59946109 END_ID=59946109 UPDATE_DELAY=5
```
## Switching from external storage to object storage
Automatic migration moves diffs stored in the database, but it does not move diffs between storage types.
To switch from external storage to object storage:
1. Move files stored on local or NFS storage to object storage manually.
1. Run the Rake task in the [previous section](#correcting-incorrectly-migrated-diffs) to change their location in the database.

View file

@ -12,24 +12,56 @@ You can read more about [personal access tokens](../user/profile/personal_access
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in GitLab 13.3.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) from GitLab Ultimate to GitLab Free in 13.6.
> - `created_after`, `created_before`, `last_used_after`, `last_used_before`, `revoked`, `search` and `state` filters were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362248) in GitLab 15.4.
Get a list of personal access tokens.
Get all personal access tokens the authenticated user has access to. By default, returns an unfiltered list of:
- Only personal access tokens created by the current user to a non-administrator.
- All personal access tokens to an administrator.
Administrators:
- Can use the `user_id` parameter to filter by a user.
- Can use other filters on all personal access tokens (GitLab 15.3 and later).
Non-administrators:
- Cannot use the `user_id` parameter to filter on any user except themselves, otherwise they receive a `401 Unauthorized` response.
- Can only filter on their own personal access tokens (GitLab 15.3 and later).
```plaintext
GET /personal_access_tokens
GET /personal_access_tokens?created_after=2022-01-01T00:00:00
GET /personal_access_tokens?created_before=2022-01-01T00:00:00
GET /personal_access_tokens?last_used_after=2022-01-01T00:00:00
GET /personal_access_tokens?last_used_before=2022-01-01T00:00:00
GET /personal_access_tokens?revoked=true
GET /personal_access_tokens?search=name
GET /personal_access_tokens?state=inactive
GET /personal_access_tokens?user_id=1
```
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
| `user_id` | integer/string | no | The ID of the user to filter by |
Supported attributes:
NOTE:
Administrators can use the `user_id` parameter to filter by a user. Non-administrators cannot filter by any user except themselves. Attempting to do so will result in a `401 Unauthorized` response.
| Attribute | Type | Required | Description |
|---------------------|----------------|----------|---------------------|
| `created_after` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs created after specified time. |
| `created_before` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs created before specified time. |
| `last_used_after` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs last used after specified time. |
| `last_used_before` | datetime (ISO 8601) | **{dotted-circle}** No | Limit results to PATs last used before specified time. |
| `revoked` | boolean | **{dotted-circle}** No | Limit results to PATs with specified revoked state. Valid values are `true` and `false`. |
| `search` | string | **{dotted-circle}** No | Limit results to PATs with name containing search string. |
| `state` | string | **{dotted-circle}** No | Limit results to PATs with specified state. Valid values are `active` and `inactive`. |
| `user_id` | integer or string | **{dotted-circle}** No | Limit results to PATs owned by specified user. |
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens"
```
Example response:
```json
[
{
@ -48,10 +80,14 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens?user_id=3"
```
Example response:
```json
[
{
@ -70,6 +106,38 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens?revoked=true"
```
Example response:
```json
[
{
"id": 41,
"name": "Revoked Test Token",
"revoked": true,
"created_at": "2022-01-01T14:31:47.729Z",
"scopes": [
"api"
],
"user_id": 8,
"last_used_at": "2022-05-18T17:58:37.550Z",
"active": false,
"expires_at": null
}
]
```
You can filter by merged attributes with:
```plaintext
GET /personal_access_tokens?revoked=true&created_before=2022-01-01
```
## Get single personal access token by ID
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362239) in GitLab 15.1.
@ -81,7 +149,7 @@ Administrators can get any token.
GET /personal_access_tokens/:id
```
| Attribute | Type | required | Description |
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer/string | yes | ID of personal access token |
@ -116,7 +184,7 @@ Revoke a personal access token using its ID.
DELETE /personal_access_tokens/:id
```
| Attribute | Type | required | Description |
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer/string | yes | ID of personal access token |

View file

@ -19,7 +19,8 @@ Note that:
- Existing projects are skipped.
- Projects in hashed storage may be skipped. For more information, see
[Importing bare repositories from hashed storage](#importing-bare-repositories-from-hashed-storage).
- The existing Git repositories ware moved from disk (removed from the original path).
- The existing Git repositories are moved from disk (removed from the original path).
- You must manually [push Git LFS objects](#push-git-lfs-objects).
To import bare repositories into a GitLab instance:
@ -152,3 +153,12 @@ projects (this may take a while if there are 1000s of projects in a namespace):
namespace = Namespace.find_by_full_path('gitlab-org')
namespace.send(:write_projects_repository_config)
```
## Push Git LFS objects
The import task doesn't import Git LFS objects. You must manually push the LFS objects to the newly
created GitLab repository using the following command:
```shell
git lfs push --all
```

View file

@ -73,26 +73,30 @@ click E "./self_managed/index.html#view-your-subscription"
With the [Customers Portal](https://customers.gitlab.com/) you can:
- [Change your personal details](#change-your-personal-details)
- [Change account owner information](#change-account-owner-information)
- [Change your company details](#change-your-company-details)
- [Change your payment method](#change-your-payment-method)
- [Change the linked account](#change-the-linked-account)
- [Change the namespace the subscription is linked to](#change-the-linked-namespace)
- [Change customers portal account password](#change-customers-portal-account-password)
### Change your personal details
### Change account owner information
Your personal details are used on invoices. Your email address is used for the Customers Portal
login and license-related email.
Account owner personal details are used on invoices. The account owner email
address is used for the Customers Portal login and license-related email.
To change your personal details, including name, billing address, and email address:
To change account owner information, including name, billing address, and email address:
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
1. Select **My account > Account details**.
1. Expand the **Personal details** section.
1. Edit your personal details.
1. Edit the personal details.
1. Select **Save changes**.
If you want to transfer ownership of the Customers Portal account
to another person, after you enter that person's personal details, you must also
[change the Customers Portal account password](#change-customers-portal-account-password).
### Change your company details
To change your company details, including company name and VAT number:

View file

@ -270,10 +270,12 @@ To [Create a new group](../group/manage.md#create-a-group) select **New group**.
### Administering Topics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
- > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
- > Merging topics [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366884) in GitLab 15.5.
You can administer all [topics](../project/working_with_projects.md#explore-topics) in the
GitLab instance from the Admin Area's Topics page.
[Topics](../project/working_with_projects.md#explore-topics) are used to categorize and find similar projects.
You can administer all topics in the GitLab instance from the Admin Area's Topics page.
To access the Topics page:
@ -295,7 +297,7 @@ insensitive and applies partial matching.
NOTE:
The assigned topics are visible only to everyone with access to the project,
but everyone can see which topics exist at all on the GitLab instance.
but everyone can see which topics exist on the GitLab instance.
Do not include sensitive information in the name of a topic.
### Administering Jobs

View file

@ -27,6 +27,12 @@ To access your user settings:
## Change your password
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23610) in GitLab 15.4 [with a flag](../../administration/feature_flags.md) named `block_weak_passwords`, weak passwords aren't accepted. Disabled by default.
FLAG:
On self-managed GitLab, by default blocking weak passwords is not available. To make it available, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `block_weak_passwords`. On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
The feature is not ready for production use.
To change your password:
1. On the top bar, in the top-right corner, select your avatar.

View file

@ -40,6 +40,9 @@ To assign topics to a project:
1. In the **Topics** text box, enter the project topics. Popular topics are suggested as you type.
1. Select **Save changes**.
If you're an instance administrator, you can administer all project topics from the
[Admin Area's Topics page](../../admin_area/index.md#administering-topics).
## Compliance frameworks **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.

View file

@ -13,6 +13,11 @@ code are saved in projects, and most features are in the scope of projects.
To view projects, on the top bar, select **Main menu > Projects > View all projects**.
NOTE:
The **Explore projects** tab is visible to unauthenticated users unless the
[**Public** visibility level](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels)
is restricted. Then the tab is visible only to signed-in users.
### Who can view the Projects page
When you select a project, the project landing page shows the project contents.
@ -46,11 +51,6 @@ To explore project topics:
The **Explore topics** tab shows a list of topics sorted by the number of associated projects.
NOTE:
The **Explore projects** tab is visible to unauthenticated users unless the
[**Public** visibility level](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels)
is restricted. Then the tab is visible only to signed-in users.
You can assign topics to a project on the [Project Settings page](settings/index.md#assign-topics-to-a-project).
If you're an instance administrator, you can administer all project topics from the

View file

@ -144,6 +144,8 @@ module.exports = (path, options = {}) => {
'three',
'monaco-editor',
'monaco-yaml',
'monaco-marker-data-provider',
'monaco-worker-manager',
'fast-mersenne-twister',
'prosemirror-markdown',
'marked',

View file

@ -4,11 +4,14 @@ module API
module Helpers
module PersonalAccessTokensHelpers
def finder_params(current_user)
if current_user.can_admin_all_resources?
{ user: user(params[:user_id]) }
else
{ user: current_user, impersonation: false }
end
user_param =
if current_user.can_admin_all_resources?
{ user: user(params[:user_id]) }
else
{ user: current_user, impersonation: false }
end
declared(params, include_missing: false).merge(user_param)
end
def user(user_id)

View file

@ -11,7 +11,15 @@ module API
success Entities::PersonalAccessToken
end
params do
optional :user_id, type: Integer, desc: 'User ID'
optional :user_id, type: Integer, desc: 'Filter PATs by User ID'
optional :revoked, type: Boolean, desc: 'Filter PATs where revoked state matches parameter'
optional :state, type: String, desc: 'Filter PATs which are either active or not',
values: %w[active inactive]
optional :created_before, type: DateTime, desc: 'Filter PATs which were created before given datetime'
optional :created_after, type: DateTime, desc: 'Filter PATs which were created after given datetime'
optional :last_used_before, type: DateTime, desc: 'Filter PATs which were used before given datetime'
optional :last_used_after, type: DateTime, desc: 'Filter PATs which were used after given datetime'
optional :search, type: String, desc: 'Filters PATs by its name'
use :pagination
end

View file

@ -13,62 +13,72 @@ module Gitlab
end
def all_time_data
aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
aggregated_metrics_data(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
aggregated_metrics_data(Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME)
end
def weekly_data
aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME))
aggregated_metrics_data(Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME)
end
private
attr_accessor :aggregated_metrics, :recorded_at
def aggregated_metrics_data(start_date:, end_date:, time_frame:)
def aggregated_metrics_data(time_frame)
aggregated_metrics.each_with_object({}) do |aggregation, data|
next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], type: :development)
next unless aggregation[:time_frame].include?(time_frame)
case aggregation[:source]
when REDIS_SOURCE
if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(
DisallowedAggregationTimeFrame.new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
)
else
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
end
when DATABASE_SOURCE
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
else
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(UnknownAggregationSource.new("Aggregation source: '#{aggregation[:source]}' must be included in #{SOURCES.keys}"))
data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
end
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, time_frame: time_frame)
end
end
def calculate_count_for_aggregation(aggregation:, start_date:, end_date:)
source = SOURCES[aggregation[:source]]
def calculate_count_for_aggregation(aggregation:, time_frame:)
with_validate_configuration(aggregation, time_frame) do
source = SOURCES[aggregation[:source]]
case aggregation[:operator]
when UNION_OF_AGGREGATED_METRICS
source.calculate_metrics_union(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
when INTERSECTION_OF_AGGREGATED_METRICS
source.calculate_metrics_intersections(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
else
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"))
Gitlab::Utils::UsageData::FALLBACK
if aggregation[:operator] == UNION_OF_AGGREGATED_METRICS
source.calculate_metrics_union(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
else
source.calculate_metrics_intersections(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
end
end
rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
failure(error)
end
def with_validate_configuration(aggregation, time_frame)
source = aggregation[:source]
unless ALLOWED_METRICS_AGGREGATIONS.include?(aggregation[:operator])
return failure(
UnknownAggregationOperator
.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}")
)
end
unless SOURCES[source]
return failure(
UnknownAggregationSource
.new("Aggregation source: '#{source}' must be included in #{SOURCES.keys}")
)
end
if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME && source == REDIS_SOURCE
return failure(
DisallowedAggregationTimeFrame
.new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
)
end
yield
end
def failure(error)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
Gitlab::Utils::UsageData::FALLBACK
end
@ -82,6 +92,17 @@ module Gitlab
def load_yaml_from_path(path)
YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
end
def time_constraints(time_frame)
case time_frame
when Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
monthly_time_range
when Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
weekly_time_range
when Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
{ start_date: nil, end_date: nil }
end
end
end
end
end

View file

@ -25,7 +25,6 @@ module Gitlab
error_tracking
ide_edit
incident_management
issues_edit
pipeline_authoring
quickactions
].freeze
@ -39,6 +38,7 @@ module Gitlab
ide_edit
importer
incident_management_alerts
issues_edit
kubernetes_agent
pipeline_authoring
search

View file

@ -192,14 +192,6 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_iteration_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_weight_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_cross_referenced
category: issues_edit
redis_slot: project_management
@ -228,18 +220,6 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_added_to_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_removed_from_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_changed_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_designs_added
category: issues_edit
redis_slot: project_management
@ -276,10 +256,6 @@
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_health_status_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- name: g_project_management_issue_cloned
category: issues_edit
redis_slot: project_management

View file

@ -143,7 +143,7 @@
"minimatch": "^3.0.4",
"monaco-editor": "^0.30.1",
"monaco-editor-webpack-plugin": "^6.0.0",
"monaco-yaml": "3.0.0",
"monaco-yaml": "4.0.0",
"mousetrap": "1.6.5",
"papaparse": "^5.3.1",
"patch-package": "^6.4.7",

View file

@ -18,9 +18,7 @@ module QA
commit.branch = "development"
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
commit.add_files([
{ file_path: file_name, content: 'pssst!' }
])
commit.add_files([{ file_path: file_name, content: 'pssst!' }])
end
end

View file

@ -20,12 +20,13 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = template_project
commit.commit_message = 'Add custom merge request template'
commit.add_files([
{
file_path: ".gitlab/merge_request_templates/#{template_name}.md",
content: template_content
}
])
commit.add_files(
[
{
file_path: ".gitlab/merge_request_templates/#{template_name}.md",
content: template_content
}
])
end
end

View file

@ -16,9 +16,7 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add new file'
commit.add_files([
{ file_path: file_name, content: 'pssst!' }
])
commit.add_files([{ file_path: file_name, content: 'pssst!' }])
end
end

View file

@ -22,9 +22,7 @@ module QA
commit.branch = branch_name
commit.start_branch = project.default_branch
commit.commit_message = 'Add new file'
commit.add_files([
{ file_path: 'test-folder/test-file.md', content: 'new content' }
])
commit.add_files([{ file_path: 'test-folder/test-file.md', content: 'new content' }])
end
project.visit!

View file

@ -22,12 +22,13 @@ module QA
before do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.add_files([
{
file_path: 'first_directory/test_file.txt',
content: "Test file content"
}
])
commit.add_files(
[
{
file_path: 'first_directory/test_file.txt',
content: "Test file content"
}
])
end
project.visit!

View file

@ -4,18 +4,18 @@ module QA
RSpec.describe 'Create' do
describe 'Open Web IDE from Diff Tab' do
files = [
{
file_path: 'file1',
content: 'test1'
},
{
file_path: 'file2',
content: 'test2'
},
{
file_path: 'file3',
content: 'test3'
}
{
file_path: 'file1',
content: 'test1'
},
{
file_path: 'file2',
content: 'test2'
},
{
file_path: 'file3',
content: 'test3'
}
]
let(:project) do

View file

@ -51,16 +51,11 @@ module QA
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: helm_upload_yaml
},
{
file_path: 'Chart.yaml',
content: helm_chart_yaml
}
])
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: helm_upload_yaml },
{ file_path: 'Chart.yaml', content: helm_chart_yaml }
])
end
end
@ -94,12 +89,7 @@ module QA
commit.project = client_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: helm_install_yaml
}
])
commit.add_files([{ file_path: '.gitlab-ci.yml', content: helm_install_yaml }])
end
end

View file

@ -54,20 +54,12 @@ module QA
commit.project = package_project
commit.commit_message = 'Add files'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: maven_upload_package_yaml
},
{
file_path: 'pom.xml',
content: package_pom_xml
},
{
file_path: 'settings.xml',
content: settings_xml
}
])
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: maven_upload_package_yaml },
{ file_path: 'pom.xml', content: package_pom_xml },
{ file_path: 'settings.xml', content: settings_xml }
])
end
end
@ -103,20 +95,12 @@ module QA
commit.project = client_project
commit.commit_message = 'Add files'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: maven_install_package_yaml
},
{
file_path: 'pom.xml',
content: client_pom_xml
},
{
file_path: 'settings.xml',
content: settings_xml
}
])
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: maven_install_package_yaml },
{ file_path: 'pom.xml', content: client_pom_xml },
{ file_path: 'settings.xml', content: settings_xml }
])
end
end
@ -251,15 +235,15 @@ module QA
package_pom_xml = ERB.new(read_fixture('package_managers/maven', 'package_pom.xml.erb')).result(binding)
with_fixtures([
{
file_path: 'pom.xml',
content: package_pom_xml
},
{
file_path: 'settings.xml',
content: settings_xml_with_pat
}
]) do |dir|
{
file_path: 'pom.xml',
content: package_pom_xml
},
{
file_path: 'settings.xml',
content: settings_xml_with_pat
}
]) do |dir|
Service::DockerRun::Maven.new(dir).publish!
end
@ -281,20 +265,12 @@ module QA
commit.project = client_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: maven_upload_package_yaml
},
{
file_path: 'pom.xml',
content: package_pom_xml
},
{
file_path: 'settings.xml',
content: settings_xml
}
])
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: maven_upload_package_yaml },
{ file_path: 'pom.xml', content: package_pom_xml },
{ file_path: 'settings.xml', content: settings_xml }
])
end
end
end

View file

@ -171,11 +171,12 @@ module QA
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
gitlab_ci_file,
pom_file,
settings_xml
])
commit.add_files(
[
gitlab_ci_file,
pom_file,
settings_xml
])
end
end

View file

@ -39,15 +39,10 @@ module QA
commit.project = package_project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: gradle_upload_yaml
},
{
file_path: 'build.gradle',
content: build_upload_gradle
}
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: gradle_upload_yaml },
{ file_path: 'build.gradle', content: build_upload_gradle }
])
end
end
@ -83,16 +78,11 @@ module QA
commit.project = client_project
commit.commit_message = 'Add files'
commit.add_files([
{
file_path: '.gitlab-ci.yml',
content: gradle_install_yaml
},
{
file_path: 'build.gradle',
content: build_install_gradle
}
])
commit.add_files(
[
{ file_path: '.gitlab-ci.yml', content: gradle_install_yaml },
{ file_path: 'build.gradle', content: build_install_gradle }
])
end
end

View file

@ -105,14 +105,7 @@ module QA
nuget_upload_yaml = ERB.new(read_fixture('package_managers/nuget', 'nuget_upload_package.yaml.erb')).result(binding)
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.update_files(
[
{
file_path: '.gitlab-ci.yml',
content: nuget_upload_yaml
}
]
)
commit.update_files([{ file_path: '.gitlab-ci.yml', content: nuget_upload_yaml }])
end
end
@ -137,9 +130,9 @@ module QA
commit.commit_message = 'Add new csproj file'
commit.add_files(
[
{
file_path: 'otherdotnet.csproj',
content: <<~EOF
{
file_path: 'otherdotnet.csproj',
content: <<~EOF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@ -148,18 +141,11 @@ module QA
</PropertyGroup>
</Project>
EOF
}
]
)
commit.update_files(
[
{
file_path: '.gitlab-ci.yml',
content: nuget_install_yaml
}
EOF
}
]
)
commit.update_files([{ file_path: '.gitlab-ci.yml', content: nuget_install_yaml }])
end
end

View file

@ -101,9 +101,9 @@ module QA
commit.commit_message = 'Add files'
commit.update_files(
[
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
stages:
- deploy
- install
@ -132,11 +132,11 @@ module QA
- if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
tags:
- "runner-for-#{project.name}"
YAML
},
{
file_path: 'dotnetcore.csproj',
content: <<~EOF
YAML
},
{
file_path: 'dotnetcore.csproj',
content: <<~EOF
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@ -145,8 +145,8 @@ module QA
</PropertyGroup>
</Project>
EOF
}
EOF
}
]
)
end

View file

@ -7,6 +7,50 @@ RSpec.describe PersonalAccessTokensFinder do
described_class.new(options, current_user)
end
describe '# searches PATs' do
using RSpec::Parameterized::TableSyntax
let_it_be(:time_token) do
create(:personal_access_token, created_at: DateTime.new(2022, 01, 02),
last_used_at: DateTime.new(2022, 01, 02))
end
let_it_be(:name_token) { create(:personal_access_token, name: 'test_1') }
let_it_be(:impersonated_token) do
create(:personal_access_token, :impersonation,
created_at: DateTime.new(2022, 01, 02),
last_used_at: DateTime.new(2022, 01, 02),
name: 'imp_token'
)
end
shared_examples 'finding tokens by user and options' do
subject { finder(option, user).execute }
it 'finds exactly' do
subject
is_expected.to contain_exactly(*result)
end
end
context 'by' do
where(:option, :user, :result) do
{ created_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
{ created_after: DateTime.new(2022, 01, 01) } | create(:admin) | lazy { [time_token, name_token, impersonated_token] }
{ last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
{ last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
{ impersonation: true } | create(:admin) | lazy { [impersonated_token] }
{ search: 'test' } | create(:admin) | lazy { [name_token] }
end
with_them do
it_behaves_like 'finding tokens by user and options'
end
end
end
describe '#execute' do
let(:user) { create(:user) }
let(:params) { {} }

View file

@ -8,10 +8,8 @@ import 'monaco-editor/esm/vs/language/css/monaco.contribution';
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
import 'monaco-editor/esm/vs/language/html/monaco.contribution';
import 'monaco-editor/esm/vs/basic-languages/monaco.contribution';
import 'monaco-yaml/lib/esm/monaco.contribution';
// This language starts trying to spin up web workers which obviously breaks in Jest environment
jest.mock('monaco-editor/esm/vs/language/typescript/tsMode');
jest.mock('monaco-yaml/lib/esm/yamlMode');
export * from 'monaco-editor/esm/vs/editor/editor.api';

View file

@ -0,0 +1,4 @@
const setDiagnosticsOptions = jest.fn();
const yamlDefaults = {};
export { setDiagnosticsOptions, yamlDefaults };

View file

@ -1,4 +1,4 @@
import { languages } from 'monaco-editor';
import { setDiagnosticsOptions } from 'monaco-yaml';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
@ -52,16 +52,12 @@ describe('~/editor/editor_ci_config_ext', () => {
});
describe('registerCiSchema', () => {
beforeEach(() => {
jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
});
describe('register validations options with monaco for yaml language', () => {
const mockProjectNamespace = 'namespace1';
const mockProjectPath = 'project1';
const getConfiguredYmlSchema = () => {
return languages.yaml.yamlDefaults.setDiagnosticsOptions.mock.calls[0][0].schemas[0];
return setDiagnosticsOptions.mock.calls[0][0].schemas[0];
};
it('with expected basic validation configuration', () => {
@ -77,8 +73,8 @@ describe('~/editor/editor_ci_config_ext', () => {
completion: true,
};
expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledTimes(1);
expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
expect(setDiagnosticsOptions).toHaveBeenCalledTimes(1);
expect(setDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining(expectedOptions),
);
});

View file

@ -1,4 +1,5 @@
import { languages } from 'monaco-editor';
import { setDiagnosticsOptions as yamlDiagnosticsOptions } from 'monaco-yaml';
import {
isTextFile,
registerLanguages,
@ -203,7 +204,6 @@ describe('WebIDE utils', () => {
};
jest.spyOn(languages.json.jsonDefaults, 'setDiagnosticsOptions');
jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
});
it('registers the given schemas with monaco for both json and yaml languages', () => {
@ -212,7 +212,7 @@ describe('WebIDE utils', () => {
expect(languages.json.jsonDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining({ schemas: [schema] }),
);
expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
expect(yamlDiagnosticsOptions).toHaveBeenCalledWith(
expect.objectContaining({ schemas: [schema] }),
);
});

View file

@ -4,7 +4,7 @@ import { GlDropdown, GlSearchBoxByType, GlDropdownItem, GlSprintf } from '@gitla
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import BranchDropdown, {
i18n,
} from '~/projects/settings/branch_rules/components/branch_dropdown.vue';
} from '~/projects/settings/branch_rules/components/edit/branch_dropdown.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import branchesQuery from '~/projects/settings/branch_rules/queries/branches.query.graphql';
import waitForPromises from 'helpers/wait_for_promises';

View file

@ -1,9 +1,9 @@
import { nextTick } from 'vue';
import { getParameterByName } from '~/lib/utils/url_utility';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RuleEdit from '~/projects/settings/branch_rules/components/rule_edit.vue';
import BranchDropdown from '~/projects/settings/branch_rules/components/branch_dropdown.vue';
import Protections from '~/projects/settings/branch_rules/components/protections/index.vue';
import RuleEdit from '~/projects/settings/branch_rules/components/edit/index.vue';
import BranchDropdown from '~/projects/settings/branch_rules/components/edit/branch_dropdown.vue';
import Protections from '~/projects/settings/branch_rules/components/edit/protections/index.vue';
jest.mock('~/lib/utils/url_utility', () => ({
getParameterByName: jest.fn().mockImplementation(() => 'main'),

View file

@ -3,10 +3,10 @@ import { GlLink } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import Protections, {
i18n,
} from '~/projects/settings/branch_rules/components/protections/index.vue';
import PushProtections from '~/projects/settings/branch_rules/components/protections/push_protections.vue';
import MergeProtections from '~/projects/settings/branch_rules/components/protections/merge_protections.vue';
import { protections } from '../../mock_data';
} from '~/projects/settings/branch_rules/components/edit/protections/index.vue';
import PushProtections from '~/projects/settings/branch_rules/components/edit/protections/push_protections.vue';
import MergeProtections from '~/projects/settings/branch_rules/components/edit/protections/merge_protections.vue';
import { protections } from '../../../mock_data';
describe('Branch Protections', () => {
let wrapper;

View file

@ -2,8 +2,8 @@ import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import MergeProtections, {
i18n,
} from '~/projects/settings/branch_rules/components/protections/merge_protections.vue';
import { membersAllowedToMerge, requireCodeOwnersApproval } from '../../mock_data';
} from '~/projects/settings/branch_rules/components/edit/protections/merge_protections.vue';
import { membersAllowedToMerge, requireCodeOwnersApproval } from '../../../mock_data';
describe('Merge Protections', () => {
let wrapper;

View file

@ -2,8 +2,8 @@ import { GlFormGroup, GlSprintf, GlFormCheckbox } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import PushProtections, {
i18n,
} from '~/projects/settings/branch_rules/components/protections/push_protections.vue';
import { membersAllowedToPush, allowForcePush } from '../../mock_data';
} from '~/projects/settings/branch_rules/components/edit/protections/push_protections.vue';
import { membersAllowedToPush, allowForcePush } from '../../../mock_data';
describe('Push Protections', () => {
let wrapper;

View file

@ -105,6 +105,31 @@ RSpec.describe PersonalAccessToken do
end
end
describe '.last_used_before' do
context 'last_used_*' do
let_it_be(:date) { DateTime.new(2022, 01, 01) }
let_it_be(:token) { create(:personal_access_token, last_used_at: date ) }
# This token should never occur in the following tests and indicates that filtering was done correctly with it
let_it_be(:never_used_token) { create(:personal_access_token) }
describe '.last_used_before' do
it 'returns personal access tokens used before the specified date only' do
expect(described_class.last_used_before(date + 1)).to contain_exactly(token)
end
end
it 'does not return token that is last_used_at after given date' do
expect(described_class.last_used_before(date + 1)).not_to contain_exactly(never_used_token)
end
describe '.last_used_after' do
it 'returns personal access tokens used after the specified date only' do
expect(described_class.last_used_after(date - 1)).to contain_exactly(token)
end
end
end
end
describe '.last_used_before_or_unused' do
let(:last_used_at) { 1.month.ago.beginning_of_hour }
let!(:unused_token) { create(:personal_access_token) }

View file

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Preloaders::ProjectRootAncestorPreloader do
let_it_be(:root_parent1) { create(:group, :private, name: 'root-1', path: 'root-1') }
let_it_be(:root_parent2) { create(:group, :private, name: 'root-2', path: 'root-2') }
let_it_be(:root_parent2) { create(:group, name: 'root-2', path: 'root-2') }
let_it_be(:guest_project) { create(:project, name: 'public guest', path: 'public-guest') }
let_it_be(:private_maintainer_project) do
create(:project, :private, name: 'b private maintainer', path: 'b-private-maintainer', namespace: root_parent1)
@ -15,7 +15,7 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
end
let_it_be(:public_maintainer_project) do
create(:project, :private, name: 'a public maintainer', path: 'a-public-maintainer', namespace: root_parent2)
create(:project, name: 'a public maintainer', path: 'a-public-maintainer', namespace: root_parent2)
end
let(:root_query_regex) { /\ASELECT.+FROM "namespaces" WHERE "namespaces"."id" = \d+/ }
@ -36,20 +36,20 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
it 'strong_memoizes the correct root_ancestor' do
pristine_projects.each do |project|
expected_parent_id = project.root_ancestor&.id
preloaded_parent_id = project.root_ancestor&.id
expect(project.parent_id).to eq(expected_parent_id)
expect(preloaded_parent_id).to eq(project.parent_id)
end
end
end
context 'when use_traversal_ids FF is enabled' do
context 'when the preloader is used' do
before do
preload_ancestors
end
context 'when no additional preloads are provided' do
before do
preload_ancestors(:group)
end
it_behaves_like 'executes N matching DB queries', 0
end
@ -57,6 +57,10 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
let(:additional_preloads) { [:route] }
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
before do
preload_ancestors
end
it_behaves_like 'executes N matching DB queries', 0, :full_path
end
end
@ -64,6 +68,17 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
context 'when using a :group sti name and passing projects in a user namespace' do
let(:projects) { [private_developer_project] }
let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
it 'does not load a nil value for root_ancestor' do
preload_ancestors(:group)
expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
end
end
end
context 'when use_traversal_ids FF is disabled' do
@ -91,9 +106,22 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
context 'when using a :group sti name and passing projects in a user namespace' do
let(:projects) { [private_developer_project] }
let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
it 'does not load a nil value for root_ancestor' do
preload_ancestors(:group)
expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
end
end
end
def preload_ancestors
described_class.new(pristine_projects, :namespace, additional_preloads).execute
private
def preload_ancestors(namespace_sti_name = :namespace)
described_class.new(pristine_projects, namespace_sti_name, additional_preloads).execute
end
end

View file

@ -4,14 +4,34 @@ require 'spec_helper'
RSpec.describe API::PersonalAccessTokens do
let_it_be(:path) { '/personal_access_tokens' }
let_it_be(:token1) { create(:personal_access_token) }
let_it_be(:token2) { create(:personal_access_token) }
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: token1.user) }
let_it_be(:current_user) { create(:user) }
describe 'GET /personal_access_tokens' do
using RSpec::Parameterized::TableSyntax
def map_id(json_resonse)
json_response.map { |pat| pat['id'] }
end
shared_examples 'response as expected' do |params|
subject { get api(path, personal_access_token: current_users_token), params: params }
it "status, count and result as expected" do
subject
if status == :bad_request
expect(json_response).to eq(result)
elsif status == :ok
expect(map_id(json_response)).to a_collection_containing_exactly(*result)
end
expect(response).to have_gitlab_http_status(status)
expect(json_response.count).to eq(result_count)
end
end
context 'logged in as an Administrator' do
let_it_be(:current_user) { create(:admin) }
let_it_be(:current_users_token) { create(:personal_access_token, user: current_user) }
it 'returns all PATs by default' do
get api(path, current_user)
@ -21,60 +41,348 @@ RSpec.describe API::PersonalAccessTokens do
end
context 'filtered with user_id parameter' do
let_it_be(:token) { create(:personal_access_token) }
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: token.user) }
it 'returns only PATs belonging to that user' do
get api(path, current_user), params: { user_id: token1.user.id }
get api(path, current_user), params: { user_id: token.user.id }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(2)
expect(json_response.first['user_id']).to eq(token1.user.id)
expect(json_response.first['user_id']).to eq(token.user.id)
expect(json_response.last['id']).to eq(token_impersonated.id)
end
end
context 'logged in as a non-Administrator' do
let_it_be(:current_user) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:token) { create(:personal_access_token, user: current_user) }
let_it_be(:other_token) { create(:personal_access_token, user: user) }
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: current_user) }
context 'filter with revoked parameter' do
let_it_be(:revoked_token) { create(:personal_access_token, revoked: true) }
let_it_be(:not_revoked_token1) { create(:personal_access_token, revoked: false) }
let_it_be(:not_revoked_token2) { create(:personal_access_token, revoked: false) }
it 'returns all PATs belonging to the signed-in user' do
get api(path, current_user, personal_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
where(:revoked, :status, :result_count, :result) do
true | :ok | 1 | lazy { [revoked_token.id] }
false | :ok | 3 | lazy { [not_revoked_token1.id, not_revoked_token2.id, current_users_token.id] }
'asdf' | :bad_request | 1 | { "error" => "revoked is invalid" }
end
context 'filtered with user_id parameter' do
it 'returns PATs belonging to the specific user' do
get api(path, current_user, personal_access_token: token), params: { user_id: current_user.id }
with_them do
it_behaves_like 'response as expected', revoked: params[:revoked]
end
end
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
context 'filter with active parameter' do
let_it_be(:inactive_token1) { create(:personal_access_token, revoked: true) }
let_it_be(:inactive_token2) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
let_it_be(:active_token) { create(:personal_access_token) }
where(:state, :status, :result_count, :result) do
'inactive' | :ok | 2 | lazy { [inactive_token1.id, inactive_token2.id] }
'active' | :ok | 2 | lazy { [active_token.id, current_users_token.id] }
'asdf' | :bad_request | 1 | { "error" => "state does not have a valid value" }
end
with_them do
it_behaves_like 'response as expected', state: params[:state]
end
end
context 'filter with created parameter' do
let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
context 'test created_before' do
where(:created_at, :status, :result_count, :result) do
'2022-01-02' | :ok | 1 | lazy { [token1.id] }
'2022-01-01' | :ok | 0 | lazy { [] }
'2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
'2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
'2022-01-01T:12:30:26' | :ok | 1 | lazy { [token1.id] }
'asdf' | :bad_request | 1 | { "error" => "created_before is invalid" }
end
it 'is unauthorized if filtered by a user other than current_user' do
get api(path, current_user, personal_access_token: token), params: { user_id: user.id }
with_them do
it_behaves_like 'response as expected', created_before: params[:created_at]
end
end
expect(response).to have_gitlab_http_status(:unauthorized)
context 'test created_after' do
where(:created_at, :status, :result_count, :result) do
'2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
'2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
'2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
'2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
(DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
'asdf' | :bad_request | 1 | { "error" => "created_after is invalid" }
end
with_them do
it_behaves_like 'response as expected', created_after: params[:created_at]
end
end
end
context 'not authenticated' do
it 'is forbidden' do
get api(path)
context 'filter with last_used parameter' do
let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
let_it_be(:never_used_token) { create(:personal_access_token) }
context 'test last_used_before' do
where(:last_used_at, :status, :result_count, :result) do
'2022-01-02' | :ok | 1 | lazy { [token1.id] }
'2022-01-01' | :ok | 0 | lazy { [] }
'2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
'2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
'2022-01-01T12:30:26' | :ok | 1 | lazy { [token1.id] }
'asdf' | :bad_request | 1 | { "error" => "last_used_before is invalid" }
end
with_them do
it_behaves_like 'response as expected', last_used_before: params[:last_used_at]
end
end
context 'test last_used_after' do
where(:last_used_at, :status, :result_count, :result) do
'2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
'2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
'2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
'2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
(DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
'asdf' | :bad_request | 1 | { "error" => "last_used_after is invalid" }
end
with_them do
it_behaves_like 'response as expected', last_used_after: params[:last_used_at]
end
end
end
context 'filter with search parameter' do
let_it_be(:token1) { create(:personal_access_token, name: 'test_1') }
let_it_be(:token2) { create(:personal_access_token, name: 'test_2') }
let_it_be(:token3) { create(:personal_access_token, name: '') }
where(:pattern, :status, :result_count, :result) do
'test' | :ok | 2 | lazy { [token1.id, token2.id] }
'' | :ok | 4 | lazy { [token1.id, token2.id, token3.id, current_users_token.id] }
'test_1' | :ok | 1 | lazy { [token1.id] }
'asdf' | :ok | 0 | lazy { [] }
end
with_them do
it_behaves_like 'response as expected', search: params[:pattern]
end
end
context 'filter created_before/created_after combined with last_used_before/last_used_after' do
let_it_be(:date) { DateTime.new(2022, 01, 02) }
let_it_be(:token1) { create(:personal_access_token, created_at: date, last_used_at: date) }
where(:date_before, :date_after, :status, :result_count, :result) do
'2022-01-03' | '2022-01-01' | :ok | 1 | lazy { [token1.id] }
'2022-01-01' | '2022-01-03' | :ok | 0 | lazy { [] }
'2022-01-03' | nil | :ok | 1 | lazy { [token1.id] }
nil | '2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
end
with_them do
it_behaves_like 'response as expected', { created_before: params[:date_before],
created_after: params[:date_after] }
it_behaves_like 'response as expected', { last_used_before: params[:date_before],
last_used_after: params[:date_after] }
end
end
context 'filter created_before and created_after combined is valid' do
let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02)) }
where(:created_before, :created_after, :status, :result) do
'2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
'2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
'2022-01-01' | '2022-01-03' | :ok | lazy { [] }
'2022-01-03' | nil | :ok | lazy { [token1.id] }
nil | '2022-01-01' | :ok | lazy { [token1.id] }
end
with_them do
it "returns all valid tokens" do
get api(path, personal_access_token: current_users_token),
params: { created_before: created_before, created_after: created_after }
expect(response).to have_gitlab_http_status(status)
expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok
end
end
end
context 'filter last_used_before and last_used_after combined is valid' do
let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 02) ) }
where(:last_used_before, :last_used_after, :status, :result) do
'2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
'2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
'2022-01-01' | '2022-01-03' | :ok | lazy { [] }
'2022-01-03' | nil | :ok | lazy { [token1.id] }
nil | '2022-01-01' | :ok | lazy { [token1.id] }
end
with_them do
it "returns all valid tokens" do
get api(path, personal_access_token: current_users_token),
params: { last_used_before: last_used_before, last_used_after: last_used_after }
expect(response).to have_gitlab_http_status(status)
expect(json_response.map { |pat| pat['id'] } ).to include(*result) if status == :ok
end
end
end
end
context 'logged in as a non-Administrator' do
let_it_be(:current_user) { create(:user) }
let_it_be(:current_users_token) { create(:personal_access_token, user: current_user) }
it 'returns all PATs belonging to the signed-in user' do
get api(path, personal_access_token: current_users_token)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
end
context 'filtered with user_id parameter' do
let_it_be(:user) { create(:user) }
it 'returns PATs belonging to the specific user' do
get api(path, current_user, personal_access_token: current_users_token), params: { user_id: current_user.id }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.count).to eq(1)
expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
end
it 'is unauthorized if filtered by a user other than current_user' do
get api(path, current_user, personal_access_token: current_users_token), params: { user_id: user.id }
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'filter with revoked parameter' do
let_it_be(:users_revoked_token) { create(:personal_access_token, revoked: true, user: current_user) }
let_it_be(:not_revoked_token) { create(:personal_access_token, revoked: false) }
let_it_be(:oter_revoked_token) { create(:personal_access_token, revoked: true) }
where(:revoked, :status, :result_count, :result) do
true | :ok | 1 | lazy { [users_revoked_token.id] }
false | :ok | 1 | lazy { [current_users_token.id] }
end
with_them do
it_behaves_like 'response as expected', revoked: params[:revoked]
end
end
context 'filter with active parameter' do
let_it_be(:users_inactive_token) { create(:personal_access_token, revoked: true, user: current_user) }
let_it_be(:inactive_token) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
let_it_be(:other_active_token) { create(:personal_access_token) }
where(:state, :status, :result_count, :result) do
'inactive' | :ok | 1 | lazy { [users_inactive_token.id] }
'active' | :ok | 1 | lazy { [current_users_token.id] }
end
with_them do
it_behaves_like 'response as expected', state: params[:state]
end
end
# The created_before filter has been extensively tested in the 'logged in as administrator' section.
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
context 'filter with created parameter' do
let_it_be(:token1) do
create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25), user: current_user )
end
let_it_be(:token2) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25)) }
let_it_be(:status) { :ok }
context 'created_before' do
let_it_be(:result_count) { 1 }
let_it_be(:result) { [token1.id] }
it_behaves_like 'response as expected', created_before: '2022-01-03'
end
context 'created_after' do
let_it_be(:result_count) { 2 }
let_it_be(:result) { [token1.id, current_users_token.id] }
it_behaves_like 'response as expected', created_after: '2022-01-01'
end
end
# The last_used_before filter has been extensively tested in the 'logged in as administrator' section.
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
context 'filter with last_used' do
let_it_be(:token1) do
create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25), user: current_user)
end
let_it_be(:token2) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25) ) }
let_it_be(:never_used_token) { create(:personal_access_token) }
let_it_be(:status) { :ok }
context 'last_used_before' do
let_it_be(:result_count) { 1 }
let_it_be(:result) { [token1.id] }
it_behaves_like 'response as expected', last_used_before: '2022-01-02'
end
context 'last_used_after' do
let_it_be(:result_count) { 2 }
let_it_be(:result) { [token1.id, current_users_token.id] }
it_behaves_like 'response as expected', last_used_after: '2022-01-01'
end
end
# The search filter has been extensively tested in the 'logged in as administrator' section.
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
context 'filter with search parameter' do
let_it_be(:token1) { create(:personal_access_token, name: 'test_1', user: current_user) }
let_it_be(:token2) { create(:personal_access_token, name: 'test_1') }
let_it_be(:token3) { create(:personal_access_token, name: '') }
where(:pattern, :status, :result_count, :result) do
'test' | :ok | 1 | lazy { [token1.id] }
'' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
'test_1' | :ok | 1 | lazy { [token1.id] }
end
with_them do
it_behaves_like 'response as expected', search: params[:pattern]
end
end
end
context 'not authenticated' do
it 'is forbidden' do
get api(path)
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
end
describe 'GET /personal_access_tokens/:id' do
let_it_be(:current_user) { create(:user) }
let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
let_it_be(:token1) { create(:personal_access_token) }
let_it_be(:user_read_only_token) { create(:personal_access_token, scopes: ['read_repository'], user: current_user) }
let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
let_it_be(:invalid_path) { "/personal_access_tokens/#{non_existing_record_id}" }
@ -136,6 +444,9 @@ RSpec.describe API::PersonalAccessTokens do
end
describe 'DELETE /personal_access_tokens/:id' do
let_it_be(:current_user) { create(:user) }
let_it_be(:token1) { create(:personal_access_token) }
let(:path) { "/personal_access_tokens/#{token1.id}" }
context 'when current_user is an administrator', :enable_admin_mode do

View file

@ -2047,10 +2047,10 @@
jest-matcher-utils "^27.0.0"
pretty-format "^27.0.0"
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
"@types/json-schema@^7.0.0", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
"@types/json5@^0.0.29":
version "0.0.29"
@ -7492,7 +7492,7 @@ js-sdsl@^4.1.4:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.13.1, js-yaml@^3.14.1:
js-yaml@^3.13.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@ -7587,7 +7587,7 @@ json5@^2.1.2, json5@^2.2.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
jsonc-parser@~3.1.0:
jsonc-parser@^3.0.0, jsonc-parser@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.1.0.tgz#73b8f0e5c940b83d03476bc2e51a20ef0932615d"
integrity sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==
@ -8840,14 +8840,31 @@ monaco-editor@^0.30.1:
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.30.1.tgz#47f8d18a0aa2264fc5654581741ab8d7bec01689"
integrity sha512-B/y4+b2O5G2gjuxIFtCE2EkM17R2NM7/3F8x0qcPsqy4V83bitJTIO4TIeZpYlzu/xy6INiY/+84BEm6+7Cmzg==
monaco-yaml@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-3.0.0.tgz#b3d59c3485bd5a161438072a8e5a8aaf74041dfd"
integrity sha512-WkgdfjCj0L2VPPwPoiwc4l8+B78FyVpSsMoufEWqe3ukm8+WygKUtmtCFOFnehmMih6tSqhy4DUtoAhfnicyZA==
monaco-marker-data-provider@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/monaco-marker-data-provider/-/monaco-marker-data-provider-1.1.1.tgz#0ca69f367152f5aa12cec2bda95f32b7403e876f"
integrity sha512-PGB7TJSZE5tmHzkxv/OEwK2RGNC2A7dcq4JRJnnj31CUAsfmw0Gl+1QTrH0W0deKhcQmQM0YVPaqgQ+0wCt8Mg==
monaco-worker-manager@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/monaco-worker-manager/-/monaco-worker-manager-2.0.1.tgz#f67c54dfca34ed4b225d5de84e77b24b4e36de8a"
integrity sha512-kdPL0yvg5qjhKPNVjJoym331PY/5JC11aPJXtCZNwWRvBr6jhkIamvYAyiY5P1AWFmNOy0aRDRoMdZfa71h8kg==
monaco-yaml@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-4.0.0.tgz#3bf8624f984665aba7e5f10c4987cecf2890e89b"
integrity sha512-7/CbvZIHE1iOQF6ny+uPclcsrBnkK54lcZugIB9SzqADljhb3TliJyYs7vouaGNDF73RWvrtZrMsWCC5N/GW+g==
dependencies:
"@types/json-schema" "^7.0.8"
js-yaml "^3.14.1"
yaml-ast-parser-custom-tags "^0.0.43"
"@types/json-schema" "^7.0.0"
jsonc-parser "^3.0.0"
monaco-marker-data-provider "^1.0.0"
monaco-worker-manager "^2.0.0"
path-browserify "^1.0.0"
prettier "^2.0.0"
vscode-languageserver-textdocument "^1.0.0"
vscode-languageserver-types "^3.0.0"
vscode-uri "^3.0.0"
yaml "^2.0.0"
mousetrap@1.6.5:
version "1.6.5"
@ -9437,6 +9454,11 @@ path-browserify@0.0.1:
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
path-browserify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@ -9670,7 +9692,7 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
prettier@2.2.1, "prettier@^1.18.2 || ^2.0.0":
prettier@2.2.1, "prettier@^1.18.2 || ^2.0.0", prettier@^2.0.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
@ -11881,6 +11903,21 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
vscode-languageserver-textdocument@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.5.tgz#838769940ece626176ec5d5a2aa2d0aa69f5095c"
integrity sha512-1ah7zyQjKBudnMiHbZmxz5bYNM9KKZYz+5VQLj+yr8l+9w3g+WAhCkUkWbhMEdC5u0ub4Ndiye/fDyS8ghIKQg==
vscode-languageserver-types@^3.0.0:
version "3.17.2"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz#b2c2e7de405ad3d73a883e91989b850170ffc4f2"
integrity sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==
vscode-uri@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84"
integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==
vue-apollo@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.7.tgz#97a031d45641faa4888a6d5a7f71c40834359704"
@ -12402,20 +12439,15 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml-ast-parser-custom-tags@^0.0.43:
version "0.0.43"
resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02"
integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ==
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.0.0-10:
version "2.0.0-10"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-10.tgz#d5b59e2d14b8683313a534f2bbc648e211a2753e"
integrity sha512-FHV8s5ODFFQXX/enJEU2EkanNl1UDBUz8oa4k5Qo/sR+Iq7VmhCDkRMb0/mjJCNeAWQ31W8WV6PYStDE4d9EIw==
yaml@^2.0.0, yaml@^2.0.0-10:
version "2.1.1"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec"
integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==
yargs-parser@^20.2.2, yargs-parser@^20.2.3:
version "20.2.9"