Add latest changes from gitlab-org/gitlab@13-6-stable-ee
This commit is contained in:
parent
1b517a5a19
commit
86a8eee1b8
|
|
@ -1,3 +1,5 @@
|
|||
import { joinPaths } from '~/lib/utils/url_utility';
|
||||
|
||||
export const pathGenerator = (imageDetails, ending = '?format=json') => {
|
||||
// this method is a temporary workaround, to be removed with graphql implementation
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/276432
|
||||
|
|
@ -12,5 +14,12 @@ export const pathGenerator = (imageDetails, ending = '?format=json') => {
|
|||
return acc;
|
||||
}, [])
|
||||
.join('/');
|
||||
return `/${basePath}/registry/repository/${imageDetails.id}/tags${ending}`;
|
||||
|
||||
return joinPaths(
|
||||
window.gon.relative_url_root,
|
||||
`/${basePath}`,
|
||||
'/registry/repository/',
|
||||
`${imageDetails.id}`,
|
||||
`tags${ending}`,
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -202,6 +202,9 @@ export default {
|
|||
shouldShowAccessibilityReport() {
|
||||
return this.mr.accessibilityReportPath;
|
||||
},
|
||||
formattedHumanAccess() {
|
||||
return (this.mr.humanAccess || '').toLowerCase();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
state(newVal, oldVal) {
|
||||
|
|
@ -439,7 +442,7 @@ export default {
|
|||
class="mr-widget-workflow"
|
||||
:pipeline-path="mr.mergeRequestAddCiConfigPath"
|
||||
:pipeline-svg-path="mr.pipelinesEmptySvgPath"
|
||||
:human-access="mr.humanAccess.toLowerCase()"
|
||||
:human-access="formattedHumanAccess"
|
||||
:user-callouts-path="mr.userCalloutsPath"
|
||||
:user-callout-feature-id="mr.suggestPipelineFeatureId"
|
||||
@dismiss="dismissSuggestPipelines"
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ module MembersHelper
|
|||
text = 'Are you sure you want to'
|
||||
|
||||
action =
|
||||
if member.request?
|
||||
if member.invite?
|
||||
"revoke the invitation for #{member.invite_email} to join"
|
||||
elsif member.request?
|
||||
if member.user == user
|
||||
'withdraw your access request for'
|
||||
else
|
||||
"deny #{member.user.name}'s request to join"
|
||||
end
|
||||
elsif member.invite?
|
||||
"revoke the invitation for #{member.invite_email} to join"
|
||||
else
|
||||
if member.user
|
||||
"remove #{member.user.name} from"
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ module Members
|
|||
|
||||
emails.each do |email|
|
||||
next if existing_member?(source, email)
|
||||
|
||||
next if existing_invite?(source, email)
|
||||
next if existing_request?(source, email)
|
||||
|
||||
if existing_user?(email)
|
||||
add_existing_user_as_member(current_user, source, params, email)
|
||||
|
|
@ -44,8 +44,7 @@ module Members
|
|||
access_level: params[:access_level],
|
||||
invite_email: email,
|
||||
created_by_id: current_user.id,
|
||||
expires_at: params[:expires_at],
|
||||
requested_at: Time.current.utc)
|
||||
expires_at: params[:expires_at])
|
||||
|
||||
unless new_member.valid? && new_member.persisted?
|
||||
errors[params[:email]] = new_member.errors.full_messages.to_sentence
|
||||
|
|
@ -92,6 +91,17 @@ module Members
|
|||
false
|
||||
end
|
||||
|
||||
def existing_request?(source, email)
|
||||
existing_request = source.requesters.with_user_by_email(email).exists?
|
||||
|
||||
if existing_request
|
||||
errors[email] = "Member cannot be invited because they already requested to join #{source.name}"
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def existing_user(email)
|
||||
User.find_by_email(email)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ module Projects
|
|||
|
||||
@project
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
message = "Unable to save #{e.record.type}: #{e.record.errors.full_messages.join(", ")} "
|
||||
message = "Unable to save #{e.inspect}: #{e.record.errors.full_messages.join(", ")}"
|
||||
fail(error: message)
|
||||
rescue => e
|
||||
@project.errors.add(:base, e.message) if @project
|
||||
|
|
@ -122,8 +122,9 @@ module Projects
|
|||
only_concrete_membership: true)
|
||||
|
||||
if group_access_level > GroupMember::NO_ACCESS
|
||||
current_user.project_authorizations.create!(project: @project,
|
||||
access_level: group_access_level)
|
||||
current_user.project_authorizations.safe_find_or_create_by!(
|
||||
project: @project,
|
||||
access_level: group_access_level)
|
||||
end
|
||||
|
||||
if Feature.enabled?(:specialized_project_authorization_workers)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add different string encoding method in rack middleware
|
||||
merge_request: 49044
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix container_registry url for relative urls
|
||||
merge_request: 48661
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Resolve Members page 500 error after Invitation sent via API
|
||||
merge_request: 48937
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix MR rendering issue when user is tool admin and not project member
|
||||
merge_request: 49258
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix error 500s creating projects concurrently
|
||||
merge_request: 48571
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update Rake check and docs to require Ruby 2.7
|
||||
merge_request: 48552
|
||||
author:
|
||||
type: changed
|
||||
|
|
@ -121,6 +121,7 @@ class ObjectStoreSettings
|
|||
|
||||
if section['enabled'] && target_config['bucket'].blank?
|
||||
missing_bucket_for(store_type)
|
||||
next
|
||||
end
|
||||
|
||||
# Map bucket (external name) -> remote_directory (internal representation)
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ Example response:
|
|||
{
|
||||
"id": 1,
|
||||
"invite_email": "member@example.org",
|
||||
"invited_at": "2020-10-22T14:13:35Z",
|
||||
"created_at": "2020-10-22T14:13:35Z",
|
||||
"access_level": 30,
|
||||
"expires_at": "2020-11-22T14:13:35Z",
|
||||
"user_name": "Raymond Smith",
|
||||
|
|
|
|||
|
|
@ -224,12 +224,6 @@ make
|
|||
sudo make install
|
||||
```
|
||||
|
||||
Then install the Bundler gem (a version below 2.x):
|
||||
|
||||
```shell
|
||||
sudo gem install bundler --no-document --version '< 2'
|
||||
```
|
||||
|
||||
## 3. Go
|
||||
|
||||
In GitLab 8.0 and later, GitLab has several daemons written in Go. To install
|
||||
|
|
|
|||
|
|
@ -45,7 +45,13 @@ Please consider using a virtual machine to run GitLab.
|
|||
|
||||
### Ruby versions
|
||||
|
||||
GitLab requires Ruby (MRI) 2.6. Beginning in GitLab 12.2, we no longer support Ruby 2.5 and lower.
|
||||
From GitLab 13.6:
|
||||
|
||||
- Ruby 2.7 and later is required.
|
||||
|
||||
From GitLab 12.2:
|
||||
|
||||
- Ruby 2.6 and later is required.
|
||||
|
||||
You must use the standard MRI implementation of Ruby.
|
||||
We love [JRuby](https://www.jruby.org/) and [Rubinius](https://github.com/rubinius/rubinius#the-rubinius-language-platform), but GitLab
|
||||
|
|
|
|||
|
|
@ -312,6 +312,8 @@ installation-specific upgrade instructions, based on how you installed GitLab:
|
|||
|
||||
### 13.6.0
|
||||
|
||||
Ruby 2.7.2 is required. GitLab will not start with Ruby 2.6.6 or older versions.
|
||||
|
||||
The required Git version is Git v2.29 or higher.
|
||||
|
||||
### 13.3.0
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ sudo service gitlab stop
|
|||
|
||||
### 3. Update Ruby
|
||||
|
||||
NOTE: Beginning in GitLab 12.2, we only support Ruby 2.6 or higher, and dropped
|
||||
support for Ruby 2.5. Be sure to upgrade if necessary.
|
||||
NOTE: Beginning in GitLab 13.6, we only support Ruby 2.7 or higher, and dropped
|
||||
support for Ruby 2.6. Be sure to upgrade if necessary.
|
||||
|
||||
You can check which version you are running with `ruby -v`.
|
||||
|
||||
|
|
@ -70,21 +70,15 @@ Download Ruby and compile it:
|
|||
|
||||
```shell
|
||||
mkdir /tmp/ruby && cd /tmp/ruby
|
||||
curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.gz
|
||||
echo '2d78048e293817f38d4ede4ebc7873013e97bb0b ruby-2.6.6.tar.gz' | shasum -c - && tar xzf ruby-2.6.6.tar.gz
|
||||
cd ruby-2.6.6
|
||||
curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz
|
||||
echo 'cb9731a17487e0ad84037490a6baf8bfa31a09e8 ruby-2.7.2.tar.gz' | shasum -c - && tar xzf ruby-2.7.2.tar.gz
|
||||
cd ruby-2.7.2
|
||||
|
||||
./configure --disable-install-rdoc
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Install Bundler:
|
||||
|
||||
```shell
|
||||
sudo gem install bundler --no-document --version '< 2'
|
||||
```
|
||||
|
||||
### 4. Update Node.js
|
||||
|
||||
NOTE: To check the minimum required Node.js version, see [Node.js versions](../install/requirements.md#nodejs-versions).
|
||||
|
|
|
|||
|
|
@ -188,15 +188,12 @@ To set your current status:
|
|||
1. Set the desired emoji and/or status message.
|
||||
1. Click **Set status**. Alternatively, you can click **Remove status** to remove your user status entirely.
|
||||
|
||||

|
||||
|
||||
or
|
||||
|
||||
1. Click your avatar.
|
||||
1. Select **Profile**.
|
||||
1. Click **Edit profile** (pencil icon).
|
||||
1. Enter your status message in the **Your status** text field.
|
||||
1. Alternatively, select the **Busy** checkbox ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259649) in GitLab 13.6}.
|
||||
1. Click **Add status emoji** (smiley face), and select the desired emoji.
|
||||
1. Click **Update profile settings**.
|
||||
|
||||
|
|
@ -204,6 +201,44 @@ You can also set your current status [using the API](../../api/users.md#user-sta
|
|||
|
||||
If you previously selected the "Busy" checkbox, remember to deselect it when you become available again.
|
||||
|
||||
## Busy status indicator
|
||||
|
||||
> - Introduced in GitLab 13.6.
|
||||
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
|
||||
> - It's disabled on GitLab.com.
|
||||
> - It's not recommended for production use.
|
||||
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-busy-status-feature).
|
||||
|
||||
To indicate to others that you are busy, you can set an indicator
|
||||
|
||||

|
||||
|
||||
To set the busy status indicator, either:
|
||||
|
||||
- Set it directly:
|
||||
|
||||
1. Click your avatar.
|
||||
1. Click **Set status**, or **Edit status** if you have already set a status.
|
||||
1. Select the **Busy** checkbox
|
||||
|
||||
- Set it on your profile:
|
||||
|
||||
1. Click your avatar.
|
||||
1. Select **Profile**.
|
||||
1. Click **Edit profile** (**{pencil}**).
|
||||
1. Select the **Busy** checkbox
|
||||
|
||||
### Enable busy status feature
|
||||
|
||||
The busy status feature is deployed behind a feature flag and is **disabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can enable it for your instance from the [rails console](../../administration/feature_flags.md#start-the-gitlab-rails-console).
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:set_user_availability_status)
|
||||
```
|
||||
|
||||
## Commit email
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21598) in GitLab 11.4.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module API
|
|||
module Entities
|
||||
class Invitation < Grape::Entity
|
||||
expose :access_level
|
||||
expose :requested_at
|
||||
expose :created_at
|
||||
expose :expires_at
|
||||
expose :invite_email
|
||||
expose :invite_token
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ module Gitlab
|
|||
# We try to encode the string from ASCII-8BIT to UTF8. If we failed to do
|
||||
# so for certain characters in the string, those chars are probably incomplete
|
||||
# multibyte characters.
|
||||
string.encode(Encoding::UTF_8).match?(NULL_BYTE_REGEX)
|
||||
string.dup.force_encoding(Encoding::UTF_8).match?(NULL_BYTE_REGEX)
|
||||
|
||||
rescue ArgumentError, Encoding::UndefinedConversionError
|
||||
# If we're here, we caught a malformed string. Return true
|
||||
true
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module SystemCheck
|
|||
set_check_pass -> { "yes (#{self.current_version})" }
|
||||
|
||||
def self.required_version
|
||||
@required_version ||= Gitlab::VersionInfo.new(2, 5, 3)
|
||||
@required_version ||= Gitlab::VersionInfo.new(2, 7, 2)
|
||||
end
|
||||
|
||||
def self.current_version
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ RSpec.describe ObjectStoreSettings do
|
|||
config['object_store']['objects']['pages'].delete('bucket')
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
expect(settings.pages['object_store']).to eq(nil)
|
||||
end
|
||||
|
||||
context 'with legacy config' do
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ describe('Utils', () => {
|
|||
id: 1,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
window.gon.relative_url_root = null;
|
||||
});
|
||||
|
||||
it('returns the fetch url when no ending is passed', () => {
|
||||
expect(pathGenerator(imageDetails)).toBe('/foo/bar/registry/repository/1/tags?format=json');
|
||||
});
|
||||
|
|
@ -16,7 +20,7 @@ describe('Utils', () => {
|
|||
expect(pathGenerator(imageDetails, '/foo')).toBe('/foo/bar/registry/repository/1/tags/foo');
|
||||
});
|
||||
|
||||
it.each`
|
||||
describe.each`
|
||||
path | name | result
|
||||
${'foo/foo'} | ${''} | ${'/foo/foo/registry/repository/1/tags?format=json'}
|
||||
${'foo/foo/foo'} | ${'foo'} | ${'/foo/foo/registry/repository/1/tags?format=json'}
|
||||
|
|
@ -26,8 +30,15 @@ describe('Utils', () => {
|
|||
${'foo/foo/baz/foo/bar'} | ${'foo/bar'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'}
|
||||
${'baz/foo/foo'} | ${'foo'} | ${'/baz/foo/registry/repository/1/tags?format=json'}
|
||||
${'baz/foo/bar'} | ${'foo'} | ${'/baz/foo/bar/registry/repository/1/tags?format=json'}
|
||||
`('returns the correct path when path is $path and name is $name', ({ name, path, result }) => {
|
||||
expect(pathGenerator({ id: 1, name, path })).toBe(result);
|
||||
`('when path is $path and name is $name', ({ name, path, result }) => {
|
||||
it('returns the correct value', () => {
|
||||
expect(pathGenerator({ id: 1, name, path })).toBe(result);
|
||||
});
|
||||
|
||||
it('produces a correct relative url', () => {
|
||||
window.gon.relative_url_root = '/gitlab';
|
||||
expect(pathGenerator({ id: 1, name, path })).toBe(`/gitlab${result}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the url unchanged when imageDetails have no name', () => {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,20 @@ describe('mrWidgetOptions', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('formattedHumanAccess', () => {
|
||||
it('when user is a tool admin but not a member of project', () => {
|
||||
vm.mr.humanAccess = null;
|
||||
|
||||
expect(vm.formattedHumanAccess).toEqual('');
|
||||
});
|
||||
|
||||
it('when user a member of the project', () => {
|
||||
vm.mr.humanAccess = 'Owner';
|
||||
|
||||
expect(vm.formattedHumanAccess).toEqual('owner');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ RSpec.describe MembersHelper do
|
|||
expect(remove_member_message(group_member_invite)).to eq "Are you sure you want to remove this orphaned member from the #{group.name} group and any subresources?"
|
||||
end
|
||||
end
|
||||
|
||||
context 'a pending member invitation with no user associated' do
|
||||
before do
|
||||
project_member_invite.update_columns(invite_email: "#{SecureRandom.hex}@example.com", invite_token: 'some-token', user_id: nil)
|
||||
end
|
||||
|
||||
it 'does not error when there is an invitation for the requestor' do
|
||||
expect(remove_member_message(project_member_invite)).to eq "Are you sure you want to revoke the invitation for #{project_member_invite.invite_email} to join the #{project.full_name} project?"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_member_title' do
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require "rack/test"
|
||||
|
||||
|
|
@ -104,6 +103,12 @@ RSpec.describe Gitlab::Middleware::HandleMalformedStrings do
|
|||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
|
||||
it 'does not reject correct encoded password with special characters' do
|
||||
env = env_for.merge(auth_env("username", "RçKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U", nil))
|
||||
|
||||
expect(subject.call(env)).not_to eq error_400
|
||||
end
|
||||
end
|
||||
|
||||
context 'in params' do
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ RSpec.describe API::Invitations do
|
|||
it 'does not transform the requester into a proper member' do
|
||||
expect do
|
||||
post api("/#{source_type.pluralize}/#{source.id}/invitations", maintainer),
|
||||
params: { email: email, access_level: Member::MAINTAINER }
|
||||
params: { email: access_requester.email, access_level: Member::MAINTAINER }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end.not_to change { source.members.count }
|
||||
|
|
@ -71,7 +71,7 @@ RSpec.describe API::Invitations do
|
|||
params: { email: email, access_level: Member::DEVELOPER }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end.to change { source.requesters.count }.by(1)
|
||||
end.to change { source.members.invite.count }.by(1)
|
||||
end
|
||||
|
||||
it 'invites a list of new email addresses' do
|
||||
|
|
@ -82,7 +82,7 @@ RSpec.describe API::Invitations do
|
|||
params: { email: email_list, access_level: Member::DEVELOPER }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end.to change { source.requesters.count }.by(2)
|
||||
end.to change { source.members.invite.count }.by(2)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ RSpec.describe API::Invitations do
|
|||
it 'invites a member' do
|
||||
expect do
|
||||
subject
|
||||
end.to change { source.requesters.count }.by(1)
|
||||
end.to change { source.members.invite.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -280,6 +280,20 @@ RSpec.describe 'Git HTTP requests' do
|
|||
project.add_developer(user)
|
||||
end
|
||||
|
||||
context 'when user is using credentials with special characters' do
|
||||
context 'with password with special characters' do
|
||||
before do
|
||||
user.update!(password: 'RKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U')
|
||||
end
|
||||
|
||||
it 'allows clones' do
|
||||
download(path, user: user.username, password: user.password) do |response|
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'but the repo is disabled' do
|
||||
let(:project) { create(:project, :wiki_repo, :private, :repository_disabled, :wiki_enabled) }
|
||||
|
||||
|
|
|
|||
|
|
@ -63,4 +63,15 @@ RSpec.describe Members::InviteService do
|
|||
expect(result[:status]).to eq(:error)
|
||||
expect(result[:message][invited_member.invite_email]).to eq("Member already invited to #{project.name}")
|
||||
end
|
||||
|
||||
it 'does not add a member with an access_request' do
|
||||
requested_member = create(:project_member, :access_request, project: project)
|
||||
|
||||
params = { email: requested_member.user.email,
|
||||
access_level: Gitlab::Access::GUEST }
|
||||
result = described_class.new(user, params).execute(project)
|
||||
|
||||
expect(result[:status]).to eq(:error)
|
||||
expect(result[:message][requested_member.user.email]).to eq("Member cannot be invited because they already requested to join #{project.name}")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue