Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-01-05 21:11:38 +00:00
parent 19a051ca1e
commit a981098583
17 changed files with 239 additions and 67 deletions

View file

@ -18,8 +18,10 @@ module Types
description: 'ID of the runner.'
field :description, GraphQL::Types::String, null: true,
description: 'Description of the runner.'
field :created_at, Types::TimeType, null: true,
description: 'Timestamp of creation of this runner.'
field :contacted_at, Types::TimeType, null: true,
description: 'Last contact from the runner.',
description: 'Timestamp of last contact from this runner.',
method: :contacted_at
field :maximum_timeout, GraphQL::Types::Int, null: true,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.'

View file

@ -4,8 +4,8 @@
module PreferencesHelper
def layout_choices
[
['Fixed', :fixed],
['Fluid', :fluid]
[s_('Layout|Fixed'), :fixed],
[s_('Layout|Fluid'), :fluid]
]
end
@ -40,9 +40,9 @@ module PreferencesHelper
def project_view_choices
[
['Files and Readme (default)', :files],
['Activity', :activity],
['Readme', :readme]
[s_('ProjectView|Files and Readme (default)'), :files],
[s_('ProjectView|Activity'), :activity],
[s_('ProjectView|Readme'), :readme]
]
end

View file

@ -2,7 +2,7 @@
- @content_class = "limit-container-width" unless fluid_layout
- user_theme_id = Gitlab::Themes.for_user(@user).id
- user_fields = { theme: user_theme_id, gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }.to_json
- @themes = Gitlab::Themes::THEMES.to_json
- @themes = Gitlab::Themes::available_themes.to_json
- data_attributes = { themes: @themes, integration_views: integration_views.to_json, user_fields: user_fields, body_classes: Gitlab::Themes.body_classes, profile_preferences_path: profile_preferences_path }
- Gitlab::Themes.each do |theme|

View file

@ -8911,7 +8911,8 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunneraccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel!`](#cirunneraccesslevel) | Access level of the runner. |
| <a id="cirunneractive"></a>`active` | [`Boolean!`](#boolean) | Indicates the runner is allowed to receive jobs. |
| <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. |
| <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Last contact from the runner. |
| <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Timestamp of last contact from this runner. |
| <a id="cirunnercreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of creation of this runner. |
| <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. |
| <a id="cirunnerexecutorname"></a>`executorName` | [`String`](#string) | Executor last advertised by the runner. Available only when feature flag `graphql_ci_runner_executor` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
| <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. |

View file

@ -4,7 +4,7 @@ group: Authentication & Authorization
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/#assignments
---
# GitLab permissions guide
# Implementing permissions
There are multiple types of permissions across GitLab, and when implementing
anything that deals with permissions, all of them should be considered.

View file

@ -7,21 +7,23 @@ module Gitlab
# Struct class representing a single Scheme
Scheme = Struct.new(:id, :name, :css_class)
SCHEMES = [
Scheme.new(1, 'White', 'white'),
Scheme.new(2, 'Dark', 'dark'),
Scheme.new(3, 'Solarized Light', 'solarized-light'),
Scheme.new(4, 'Solarized Dark', 'solarized-dark'),
Scheme.new(5, 'Monokai', 'monokai'),
Scheme.new(6, 'None', 'none')
].freeze
def self.available_schemes
[
Scheme.new(1, s_('SynthaxHighlightingTheme|Light'), 'white'),
Scheme.new(2, s_('SynthaxHighlightingTheme|Dark'), 'dark'),
Scheme.new(3, s_('SynthaxHighlightingTheme|Solarized Light'), 'solarized-light'),
Scheme.new(4, s_('SynthaxHighlightingTheme|Solarized Dark'), 'solarized-dark'),
Scheme.new(5, s_('SynthaxHighlightingTheme|Monokai'), 'monokai'),
Scheme.new(6, s_('SynthaxHighlightingTheme|None'), 'none')
]
end
# Convenience method to get a space-separated String of all the color scheme
# classes that might be applied to a code block.
#
# Returns a String
def self.body_classes
SCHEMES.collect(&:css_class).uniq.join(' ')
available_schemes.collect(&:css_class).uniq.join(' ')
end
# Get a Scheme by its ID
@ -32,12 +34,12 @@ module Gitlab
#
# Returns a Scheme
def self.by_id(id)
SCHEMES.detect { |s| s.id == id } || default
available_schemes.detect { |s| s.id == id } || default
end
# Returns the number of defined Schemes
def self.count
SCHEMES.size
available_schemes.size
end
# Get the default Scheme
@ -51,7 +53,7 @@ module Gitlab
#
# Yields the Scheme object
def self.each(&block)
SCHEMES.each(&block)
available_schemes.each(&block)
end
# Get the Scheme for the specified user, or the default
@ -68,7 +70,7 @@ module Gitlab
end
def self.valid_ids
SCHEMES.map(&:id)
available_schemes.map(&:id)
end
end
end

View file

@ -53,17 +53,11 @@ module Gitlab
params = {
body_stream: file,
headers: {
'Content-Length' => object.size.to_s,
'Content-Type' => 'application/octet-stream',
'User-Agent' => GIT_LFS_USER_AGENT
}.merge(upload_action['header'] || {})
headers: upload_headers(object, upload_action)
}
authenticated = true if params[:headers].key?('Authorization')
params[:basic_auth] = basic_auth unless authenticated
rsp = Gitlab::HTTP.put(upload_action['href'], params)
url = set_basic_auth_and_extract_lfs_url!(params, upload_action['href'])
rsp = Gitlab::HTTP.put(url, params)
raise ObjectUploadError.new(http_response: rsp) unless rsp.success?
ensure
@ -76,20 +70,51 @@ module Gitlab
headers: build_request_headers(verify_action['header'])
}
authenticated = true if params[:headers].key?('Authorization')
params[:basic_auth] = basic_auth unless authenticated
rsp = Gitlab::HTTP.post(verify_action['href'], params)
url = set_basic_auth_and_extract_lfs_url!(params, verify_action['href'])
rsp = Gitlab::HTTP.post(url, params)
raise ObjectVerifyError.new(http_response: rsp) unless rsp.success?
end
private
def set_basic_auth_and_extract_lfs_url!(params, raw_url)
authenticated = true if params[:headers].key?('Authorization')
params[:basic_auth] = basic_auth unless authenticated
strip_userinfo = authenticated || params[:basic_auth].present?
lfs_url(raw_url, strip_userinfo)
end
def build_request_headers(extra_headers = nil)
DEFAULT_HEADERS.merge(extra_headers || {})
end
def upload_headers(object, upload_action)
# This uses the httprb library to handle case-insensitive HTTP headers
headers = ::HTTP::Headers.new
headers.merge!(upload_action['header'])
transfer_encodings = Array(headers['Transfer-Encoding']&.split(',')).map(&:strip)
headers['Content-Length'] = object.size.to_s unless transfer_encodings.include?('chunked')
headers['Content-Type'] = 'application/octet-stream'
headers['User-Agent'] = GIT_LFS_USER_AGENT
headers.to_h
end
def lfs_url(raw_url, strip_userinfo)
# HTTParty will give precedence to the username/password
# specified in the URL. This causes problems with Azure DevOps,
# which includes a username in the URL. Stripping the userinfo
# from the URL allows the provided HTTP Basic Authentication
# credentials to be used.
if strip_userinfo
Gitlab::UrlSanitizer.new(raw_url).sanitized_url
else
raw_url
end
end
attr_reader :credentials
def batch_url

View file

@ -13,26 +13,28 @@ module Gitlab
Theme = Struct.new(:id, :name, :css_class, :css_filename, :primary_color)
# All available Themes
THEMES = [
Theme.new(1, 'Indigo', 'ui-indigo', 'theme_indigo', '#292961'),
Theme.new(6, 'Light Indigo', 'ui-light-indigo', 'theme_light_indigo', '#4b4ba3'),
Theme.new(4, 'Blue', 'ui-blue', 'theme_blue', '#1a3652'),
Theme.new(7, 'Light Blue', 'ui-light-blue', 'theme_light_blue', '#2261a1'),
Theme.new(5, 'Green', 'ui-green', 'theme_green', '#0d4524'),
Theme.new(8, 'Light Green', 'ui-light-green', 'theme_light_green', '#156b39'),
Theme.new(9, 'Red', 'ui-red', 'theme_red', '#691a16'),
Theme.new(10, 'Light Red', 'ui-light-red', 'theme_light_red', '#a62e21'),
Theme.new(2, 'Dark', 'ui-dark', 'theme_dark', '#303030'),
Theme.new(3, 'Light', 'ui-light', 'theme_light', '#666'),
Theme.new(11, 'Dark Mode (alpha)', 'gl-dark', nil, '#303030')
].freeze
def available_themes
[
Theme.new(1, s_('NavigationTheme|Indigo'), 'ui-indigo', 'theme_indigo', '#292961'),
Theme.new(6, s_('NavigationTheme|Light Indigo'), 'ui-light-indigo', 'theme_light_indigo', '#4b4ba3'),
Theme.new(4, s_('NavigationTheme|Blue'), 'ui-blue', 'theme_blue', '#1a3652'),
Theme.new(7, s_('NavigationTheme|Light Blue'), 'ui-light-blue', 'theme_light_blue', '#2261a1'),
Theme.new(5, s_('NavigationTheme|Green'), 'ui-green', 'theme_green', '#0d4524'),
Theme.new(8, s_('NavigationTheme|Light Green'), 'ui-light-green', 'theme_light_green', '#156b39'),
Theme.new(9, s_('NavigationTheme|Red'), 'ui-red', 'theme_red', '#691a16'),
Theme.new(10, s_('NavigationTheme|Light Red'), 'ui-light-red', 'theme_light_red', '#a62e21'),
Theme.new(2, s_('NavigationTheme|Dark'), 'ui-dark', 'theme_dark', '#303030'),
Theme.new(3, s_('NavigationTheme|Light'), 'ui-light', 'theme_light', '#666'),
Theme.new(11, s_('NavigationTheme|Dark Mode (alpha)'), 'gl-dark', nil, '#303030')
]
end
# Convenience method to get a space-separated String of all the theme
# classes that might be applied to the `body` element
#
# Returns a String
def body_classes
THEMES.collect(&:css_class).uniq.join(' ')
available_themes.collect(&:css_class).uniq.join(' ')
end
# Get a Theme by its ID
@ -43,12 +45,12 @@ module Gitlab
#
# Returns a Theme
def by_id(id)
THEMES.detect { |t| t.id == id } || default
available_themes.detect { |t| t.id == id } || default
end
# Returns the number of defined Themes
def count
THEMES.size
available_themes.size
end
# Get the default Theme
@ -62,7 +64,7 @@ module Gitlab
#
# Yields the Theme object
def each(&block)
THEMES.each(&block)
available_themes.each(&block)
end
# Get the Theme for the specified user, or the default
@ -79,7 +81,7 @@ module Gitlab
end
def self.valid_ids
THEMES.map(&:id)
available_themes.map(&:id)
end
private
@ -87,7 +89,7 @@ module Gitlab
def default_id
@default_id ||= begin
id = Gitlab.config.gitlab.default_theme.to_i
theme_ids = THEMES.map(&:id)
theme_ids = available_themes.map(&:id)
theme_ids.include?(id) ? id : APPLICATION_DEFAULT
end

View file

@ -20827,6 +20827,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project."
msgstr ""
msgid "Layout|Fixed"
msgstr ""
msgid "Layout|Fluid"
msgstr ""
msgid "Lead Time"
msgstr ""
@ -23274,6 +23280,39 @@ msgstr ""
msgid "Navigation bar"
msgstr ""
msgid "NavigationTheme|Blue"
msgstr ""
msgid "NavigationTheme|Dark"
msgstr ""
msgid "NavigationTheme|Dark Mode (alpha)"
msgstr ""
msgid "NavigationTheme|Green"
msgstr ""
msgid "NavigationTheme|Indigo"
msgstr ""
msgid "NavigationTheme|Light"
msgstr ""
msgid "NavigationTheme|Light Blue"
msgstr ""
msgid "NavigationTheme|Light Green"
msgstr ""
msgid "NavigationTheme|Light Indigo"
msgstr ""
msgid "NavigationTheme|Light Red"
msgstr ""
msgid "NavigationTheme|Red"
msgstr ""
msgid "Nav|Help"
msgstr ""
@ -28117,6 +28156,15 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
msgid "ProjectView|Activity"
msgstr ""
msgid "ProjectView|Files and Readme (default)"
msgstr ""
msgid "ProjectView|Readme"
msgstr ""
msgid "Projects"
msgstr ""
@ -34495,6 +34543,24 @@ msgstr ""
msgid "Syntax is incorrect."
msgstr ""
msgid "SynthaxHighlightingTheme|Dark"
msgstr ""
msgid "SynthaxHighlightingTheme|Light"
msgstr ""
msgid "SynthaxHighlightingTheme|Monokai"
msgstr ""
msgid "SynthaxHighlightingTheme|None"
msgstr ""
msgid "SynthaxHighlightingTheme|Solarized Dark"
msgstr ""
msgid "SynthaxHighlightingTheme|Solarized Light"
msgstr ""
msgid "System"
msgstr ""

View file

@ -6,8 +6,6 @@ module QA
module_function
def while_signed_in(as: nil, address: :gitlab, admin: false)
Page::Main::Menu.perform(&:sign_out_if_signed_in)
sign_in(as: as, address: address, admin: admin)
result = yield
@ -23,9 +21,10 @@ module QA
end
def sign_in(as: nil, address: :gitlab, skip_page_validation: false, admin: false)
Page::Main::Login.perform { |p| p.redirect_to_login_page(address) }
unless Page::Main::Login.perform(&:on_login_page?)
Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?)
Runtime::Browser.visit(address, Page::Main::Login)
end
Page::Main::Login.perform do |login|

View file

@ -386,6 +386,10 @@ module QA
end
end
def current_host
URI(page.current_url).host
end
def self.path
raise NotImplementedError
end

View file

@ -156,6 +156,11 @@ module QA
sign_in_using_credentials(user: user)
end
def redirect_to_login_page(address)
desired_host = URI(Runtime::Scenario.send("#{address}_address")).host
Runtime::Browser.visit(address, Page::Main::Login) if desired_host != current_host
end
private
def sign_in_using_gitlab_credentials(user:, skip_page_validation: false)

View file

@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
it 'contains attributes related to a runner' do
expected_fields = %w[
id description contacted_at maximum_timeout access_level active status
id description created_at contacted_at maximum_timeout access_level active status
version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url user_permissions executor_name
]

View file

@ -15,7 +15,7 @@ RSpec.describe Gitlab::ColorSchemes do
describe '.by_id' do
it 'returns a scheme by its ID' do
expect(described_class.by_id(1).name).to eq 'White'
expect(described_class.by_id(1).name).to eq 'Light'
expect(described_class.by_id(4).name).to eq 'Solarized Dark'
end
end

View file

@ -114,6 +114,52 @@ RSpec.describe Gitlab::Lfs::Client do
end
end
context 'server returns 200 OK with a chunked transfer request' do
before do
upload_action['header']['Transfer-Encoding'] = 'gzip, chunked'
end
it "makes an HTTP PUT with expected parameters" do
stub_upload(object: object, headers: upload_action['header'], chunked_transfer: true).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
context 'server returns 200 OK with a username and password in the URL' do
let(:base_url) { "https://someuser:testpass@example.com" }
it "makes an HTTP PUT with expected parameters" do
stub_upload(
object: object,
headers: basic_auth_headers.merge(upload_action['header']),
url: "https://example.com/some/file"
).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
context 'no credentials in client' do
subject(:lfs_client) { described_class.new(base_url, credentials: {}) }
context 'server returns 200 OK with credentials in URL' do
let(:creds) { 'someuser:testpass' }
let(:base_url) { "https://#{creds}@example.com" }
let(:auth_headers) { { 'Authorization' => "Basic #{Base64.strict_encode64(creds)}" } }
it "makes an HTTP PUT with expected parameters" do
stub_upload(
object: object,
headers: auth_headers.merge(upload_action['header']),
url: "https://example.com/some/file"
).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
end
context 'server returns 200 OK to an unauthenticated request' do
it "makes an HTTP PUT with expected parameters" do
stub = stub_upload(
@ -171,16 +217,21 @@ RSpec.describe Gitlab::Lfs::Client do
end
end
def stub_upload(object:, headers:)
def stub_upload(object:, headers:, url: upload_action['href'], chunked_transfer: false)
headers = {
'Content-Type' => 'application/octet-stream',
'Content-Length' => object.size.to_s,
'User-Agent' => git_lfs_user_agent
}.merge(headers)
stub_request(:put, upload_action['href']).with(
if chunked_transfer
headers['Transfer-Encoding'] = 'gzip, chunked'
else
headers['Content-Length'] = object.size.to_s
end
stub_request(:put, url).with(
body: object.file.read,
headers: headers.merge('Content-Length' => object.size.to_s)
headers: headers
)
end
end
@ -196,11 +247,25 @@ RSpec.describe Gitlab::Lfs::Client do
end
end
context 'server returns 200 OK with a username and password in the URL' do
let(:base_url) { "https://someuser:testpass@example.com" }
it "makes an HTTP PUT with expected parameters" do
stub_verify(
object: object,
headers: basic_auth_headers.merge(verify_action['header']),
url: "https://example.com/some/file/verify"
).to_return(status: 200)
lfs_client.verify!(object, verify_action, authenticated: true)
end
end
context 'server returns 200 OK to an unauthenticated request' do
it "makes an HTTP POST with expected parameters" do
stub = stub_verify(
object: object,
headers: basic_auth_headers.merge(upload_action['header'])
headers: basic_auth_headers.merge(verify_action['header'])
).to_return(status: 200)
lfs_client.verify!(object, verify_action, authenticated: false)
@ -238,14 +303,14 @@ RSpec.describe Gitlab::Lfs::Client do
end
end
def stub_verify(object:, headers:)
def stub_verify(object:, headers:, url: verify_action['href'])
headers = {
'Accept' => git_lfs_content_type,
'Content-Type' => git_lfs_content_type,
'User-Agent' => git_lfs_user_agent
}.merge(headers)
stub_request(:post, verify_action['href']).with(
stub_request(:post, url).with(
body: object.to_json(only: [:oid, :size]),
headers: headers
)

View file

@ -28,7 +28,7 @@ RSpec.describe Gitlab::Themes, lib: true do
it 'prevents an infinite loop when configuration default is invalid' do
default = described_class::APPLICATION_DEFAULT
themes = described_class::THEMES
themes = described_class.available_themes
config = double(default_theme: 0).as_null_object
allow(Gitlab).to receive(:config).and_return(config)

View file

@ -57,6 +57,7 @@ RSpec.describe 'Query.runner(id)' do
expect(runner_data).to match a_hash_including(
'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
'description' => runner.description,
'createdAt' => runner.created_at&.iso8601,
'contactedAt' => runner.contacted_at&.iso8601,
'version' => runner.version,
'shortSha' => runner.short_sha,