Skip to content
Snippets Groups Projects
Commit 2a31f612 authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖
Browse files

Automatic merge of gitlab-org/gitlab master

parents df838d7e 2a039f83
No related branches found
No related tags found
1 merge request!102774Sync security changes back to canonical
Showing
with 278 additions and 77 deletions
......@@ -53,9 +53,10 @@ export const initCopyCodeButton = (selector = '#content-body') => {
customElements.define('copy-code', CopyCodeButton);
}
const exclude = document.querySelector('.file-content.code'); // this behavior is not needed when viewing raw file content, so excluding it as the unnecessary dom lookups can become expensive
const el = document.querySelector(selector);
if (!el) return () => {};
if (!el || exclude) return () => {};
const observer = new MutationObserver(() => addCodeButton());
......
......@@ -15,8 +15,14 @@ export default {
mounted() {
handleBlobRichViewer(this.$refs.content, this.type);
},
safeHtmlConfig: {
ADD_TAGS: ['copy-code'],
},
};
</script>
<template>
<markdown-field-view ref="content" v-safe-html="richViewer || content" />
<markdown-field-view
ref="content"
v-safe-html:[$options.safeHtmlConfig]="richViewer || content"
/>
</template>
<script>
import { GlIntersectionObserver, GlSafeHtmlDirective } from '@gitlab/ui';
import { scrollToElement } from '~/lib/utils/common_utils';
import ChunkLine from './chunk_line.vue';
/*
......@@ -46,6 +47,11 @@ export default {
required: false,
default: 0,
},
totalChunks: {
type: Number,
required: false,
default: 0,
},
language: {
type: String,
required: false,
......@@ -56,11 +62,27 @@ export default {
required: true,
},
},
data() {
return {
isLoading: true,
};
},
computed: {
lines() {
return this.content.split('\n');
},
},
created() {
window.requestIdleCallback(() => {
this.isLoading = false;
const { hash } = this.$route;
if (hash && this.totalChunks > 0 && this.totalChunks === this.chunkIndex + 1) {
// when the last chunk is loaded scroll to the hash
scrollToElement(hash, { behavior: 'auto' });
}
});
},
methods: {
handleChunkAppear() {
if (!this.isHighlighted) {
......@@ -85,17 +107,18 @@ export default {
:blame-path="blamePath"
/>
</div>
<div v-else class="gl-display-flex gl-text-transparent">
<div v-else-if="!isLoading" class="gl-display-flex gl-text-transparent">
<div class="gl-display-flex gl-flex-direction-column content-visibility-auto">
<span
v-for="(n, index) in totalLines"
v-once
:id="`L${calculateLineNumber(index)}`"
:key="index"
data-testid="line-number"
v-text="calculateLineNumber(index)"
></span>
</div>
<div class="gl-white-space-pre-wrap!" data-testid="content" v-text="content"></div>
<div v-once class="gl-white-space-pre-wrap!" data-testid="content">{{ content }}</div>
</div>
</gl-intersection-observer>
</template>
......@@ -65,6 +65,9 @@ export default {
!supportedLanguages.includes(this.blob.language?.toLowerCase())
);
},
totalChunks() {
return Object.keys(this.chunks).length;
},
},
async created() {
addBlobLinksTracking();
......@@ -217,6 +220,7 @@ export default {
:chunk-index="index"
:language="chunk.language"
:blame-path="blob.blamePath"
:total-chunks="totalChunks"
@appear="highlightChunk"
/>
</div>
......
# frozen_string_literal: true
module Packages
module Rpm
module RepositoryMetadata
class BuildFilelistXml < ::Packages::Rpm::RepositoryMetadata::BaseBuilder
ROOT_TAG = 'filelists'
ROOT_ATTRIBUTES = {
xmlns: 'http://linux.duke.edu/metadata/filelists',
packages: '0'
}.freeze
end
end
end
end
# frozen_string_literal: true
module Packages
module Rpm
module RepositoryMetadata
class BuildOtherXml < ::Packages::Rpm::RepositoryMetadata::BaseBuilder
ROOT_TAG = 'otherdata'
ROOT_ATTRIBUTES = {
xmlns: 'http://linux.duke.edu/metadata/other',
packages: '0'
}.freeze
end
end
end
end
# frozen_string_literal: true
module Packages
module Rpm
module RepositoryMetadata
class BuildOtherXmlService
ROOT_TAG = 'otherdata'
ROOT_ATTRIBUTES = {
xmlns: 'http://linux.duke.edu/metadata/other',
packages: '0'
}.freeze
def initialize(data)
@data = data
end
def execute
builder = Nokogiri::XML::Builder.new do |xml|
xml.package(pkgid: data[:pkgid], name: data[:name], arch: data[:arch]) do
xml.version epoch: data[:epoch], ver: data[:version], rel: data[:release]
build_changelog_nodes(xml)
end
end
Nokogiri::XML(builder.to_xml).at('package')
end
private
attr_reader :data
def build_changelog_nodes(xml)
data[:changelogs].each do |changelog|
xml.changelog changelog[:changelogtext], date: changelog[:changelogtime]
end
end
end
end
end
end
......@@ -2,7 +2,7 @@
module Packages
module Rpm
module RepositoryMetadata
class BuildPrimaryXml < ::Packages::Rpm::RepositoryMetadata::BaseBuilder
class BuildPrimaryXmlService
ROOT_TAG = 'metadata'
ROOT_ATTRIBUTES = {
xmlns: 'http://linux.duke.edu/metadata/common',
......@@ -11,19 +11,19 @@ class BuildPrimaryXml < ::Packages::Rpm::RepositoryMetadata::BaseBuilder
}.freeze
# Nodes that have only text without attributes
REQUIRED_BASE_ATTRIBUTES = %i[name arch summary description].freeze
NOT_REQUIRED_BASE_ATTRIBUTES = %i[url packager].freeze
BASE_ATTRIBUTES = %i[name arch summary description url packager].freeze
FORMAT_NODE_BASE_ATTRIBUTES = %i[license vendor group buildhost sourcerpm].freeze
private
def initialize(data)
@data = data
end
def build_new_node
def execute
builder = Nokogiri::XML::Builder.new do |xml|
xml.package(type: :rpm, 'xmlns:rpm': 'http://linux.duke.edu/metadata/rpm') do
build_required_base_attributes(xml)
build_not_required_base_attributes(xml)
build_base_attributes(xml)
xml.version epoch: data[:epoch], ver: data[:version], rel: data[:release]
xml.checksum data[:checksum], type: 'sha256', pkgid: 'YES'
xml.checksum data[:pkgid], type: 'sha256', pkgid: 'YES'
xml.size package: data[:packagesize], installed: data[:installedsize], archive: data[:archivesize]
xml.time file: data[:filetime], build: data[:buildtime]
xml.location href: data[:location] if data[:location].present?
......@@ -34,14 +34,12 @@ def build_new_node
Nokogiri::XML(builder.to_xml).at('package')
end
def build_required_base_attributes(xml)
REQUIRED_BASE_ATTRIBUTES.each do |attribute|
xml.method_missing(attribute, data[attribute])
end
end
private
attr_reader :data
def build_not_required_base_attributes(xml)
NOT_REQUIRED_BASE_ATTRIBUTES.each do |attribute|
def build_base_attributes(xml)
BASE_ATTRIBUTES.each do |attribute|
xml.method_missing(attribute, data[attribute]) if data[attribute].present?
end
end
......
......@@ -2,7 +2,7 @@
module Packages
module Rpm
module RepositoryMetadata
class BuildRepomdXml
class BuildRepomdXmlService
attr_reader :data
ROOT_ATTRIBUTES = {
......
......@@ -2,15 +2,25 @@
module Packages
module Rpm
module RepositoryMetadata
class BaseBuilder
def initialize(xml: nil, data: {})
class UpdateXmlService
BUILDERS = {
other: ::Packages::Rpm::RepositoryMetadata::BuildOtherXmlService,
primary: ::Packages::Rpm::RepositoryMetadata::BuildPrimaryXmlService
}.freeze
def initialize(filename:, xml: nil, data: {})
@builder_class = BUILDERS[filename]
raise ArgumentError, "Filename must be one of: #{BUILDERS.keys.join(', ')}" if @builder_class.nil?
@xml = Nokogiri::XML(xml) if xml.present?
@data = data
@filename = filename
end
def execute
return build_empty_structure if xml.blank?
remove_existing_packages
update_xml_document
update_package_count
xml.to_xml
......@@ -18,27 +28,32 @@ def execute
private
attr_reader :xml, :data
attr_reader :xml, :data, :builder_class, :filename
def build_empty_structure
Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
xml.method_missing(self.class::ROOT_TAG, self.class::ROOT_ATTRIBUTES)
xml.method_missing(builder_class::ROOT_TAG, builder_class::ROOT_ATTRIBUTES)
end.to_xml
end
def update_xml_document
# Add to the root xml element a new package metadata node
xml.at(self.class::ROOT_TAG).add_child(build_new_node)
xml.at(builder_class::ROOT_TAG).add_child(builder_class.new(data).execute)
end
def update_package_count
packages_count = xml.css("//#{self.class::ROOT_TAG}/package").count
packages_count = xml.css("//#{builder_class::ROOT_TAG}/package").count
xml.at(self.class::ROOT_TAG).attributes["packages"].value = packages_count.to_s
xml.at(builder_class::ROOT_TAG).attributes["packages"].value = packages_count.to_s
end
def build_new_node
raise NotImplementedError, "#{self.class} should implement #{__method__}"
def remove_existing_packages
case filename
when :primary
xml.search("checksum:contains('#{data[:pkgid]}')").each { _1.parent&.remove }
else
xml.search("[pkgid='#{data[:pkgid]}']").each(&:remove)
end
end
end
end
......
......@@ -27,6 +27,7 @@ options:
- i_package_pypi_deploy_token
- i_package_rubygems_deploy_token
- i_package_terraform_module_deploy_token
- i_package_rpm_deploy_token
distribution:
- ee
- ce
......
---
data_category: optional
key_path: redis_hll_counters.user_packages.i_package_rpm_user_weekly
description: A weekly count of users that have published an rpm package to the registry
product_section: ops
product_stage: package
product_group: package
product_category: package_registry
value_type: number
status: active
milestone: '15.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97133
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- i_package_rpm_user
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
data_category: optional
key_path: redis_hll_counters.deploy_token_packages.i_package_rpm_deploy_token_weekly
description: A weekly count of RPM packages published to the registry using a deploy token
product_section: ops
product_stage: package
product_group: package
product_category: package_registry
value_type: number
status: active
milestone: '15.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97133
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- i_package_rpm_deploy_token
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
data_category: optional
key_path: counts.package_events_i_package_rpm_pull_package
description: A count of RPM packages that have been downloaded
product_section: ops
product_stage: package
product_group: package
product_category: package_registry
value_type: number
status: active
milestone: '15.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97133
time_frame: all
data_source: redis
instrumentation_class: RedisMetric
options:
prefix: package_events
event: i_package_rpm_pull_package
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
data_category: optional
key_path: counts.package_events_i_package_rpm_push_package
description: A count of RPM packages that have been published
product_section: ops
product_stage: package
product_group: package
product_category: package_registry
value_type: number
status: active
milestone: '15.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97133
time_frame: all
data_source: redis
instrumentation_class: RedisMetric
options:
prefix: package_events
event: i_package_rpm_push_package
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
......@@ -28,9 +28,7 @@ def merge_error
end
def push_error(change_size = 0)
"Your push to this repository has been rejected because the namespace storage limit " \
"of #{formatted(limit)} has been reached. " \
"Reduce your namespace storage or purchase additional storage."
self.class.storage_limit_reached_error_msg
end
def new_changes_error
......@@ -45,6 +43,15 @@ def above_size_limit_message
"Please contact your GitLab administrator for more information."
end
def self.storage_limit_reached_error_msg
_(
"Your action has been rejected because the namespace storage limit has been reached. " \
"For more information, visit %{doc_url}." % {
doc_url: Rails.application.routes.url_helpers.help_page_url('user/usage_quotas')
}
)
end
private
def formatted(number)
......
......@@ -26,7 +26,10 @@
it 'rejects the push' do
expect do
push_changes("#{Gitlab::Git::BLANK_SHA} #{sha_with_smallest_changes} refs/heads/master")
end.to raise_error(described_class::ForbiddenError, /Your push to this repository has been rejected/)
end.to raise_error(
described_class::ForbiddenError,
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
context 'when deleting a branch' do
......
......@@ -18,11 +18,9 @@
describe '#commit_error' do
it 'returns the expected message' do
expected_message = "Your push to this repository has been rejected because " \
"the namespace storage limit of 10 MB has been reached. " \
"Reduce your namespace storage or purchase additional storage."
expect(error_message.commit_error).to eq(expected_message)
expect(error_message.commit_error).to eq(
described_class.storage_limit_reached_error_msg
)
end
end
......@@ -39,11 +37,9 @@
describe '#push_error' do
it 'returns the expected message' do
expected_message = "Your push to this repository has been rejected because " \
"the namespace storage limit of 10 MB has been reached. " \
"Reduce your namespace storage or purchase additional storage."
expect(error_message.push_error).to eq(expected_message)
expect(error_message.push_error).to eq(
described_class.storage_limit_reached_error_msg
)
end
end
......
......@@ -189,9 +189,7 @@
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(
'Your push to this repository has been rejected because the ' \
'namespace storage limit of 5 MB has been reached. ' \
'Reduce your namespace storage or purchase additional storage.'
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
end
......@@ -246,9 +244,7 @@
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(
'Your push to this repository has been rejected because the ' \
'namespace storage limit of 5 MB has been reached. ' \
'Reduce your namespace storage or purchase additional storage.'
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
end
......
......@@ -42,9 +42,7 @@ def route(file_path = nil)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(
'Your push to this repository has been rejected because the ' \
'namespace storage limit of 5 MB has been reached. ' \
'Reduce your namespace storage or purchase additional storage.'
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
end
......@@ -73,9 +71,7 @@ def route(file_path = nil)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(
'Your push to this repository has been rejected because the ' \
'namespace storage limit of 5 MB has been reached. ' \
'Reduce your namespace storage or purchase additional storage.'
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
end
......@@ -103,9 +99,7 @@ def route(file_path = nil)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']).to eq(
'Your push to this repository has been rejected because the ' \
'namespace storage limit of 5 MB has been reached. ' \
'Reduce your namespace storage or purchase additional storage.'
EE::Gitlab::NamespaceStorageSizeErrorMessage.storage_limit_reached_error_msg
)
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment