Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-03-27 09:16:21 +00:00
parent bf360857d9
commit ff3955ef8e
30 changed files with 284 additions and 280 deletions

View File

@ -20,11 +20,7 @@ gem 'bootsnap', '~> 1.16.0', require: false
# Pin openssl to match the version bundled with our supported Rubies.
# See https://stdgems.org/openssl/#gem-version.
gem 'openssl', '2.2.2'
# This gem was originally bundled with Ruby 2.7, but is unbundled as of Ruby 3.
# Since the latest version caused problems with GitLab, we pin this to an older
# version for now.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/376417
gem 'ipaddr', '1.2.2'
gem 'ipaddr', '~> 1.2.5'
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'

View File

@ -302,7 +302,7 @@
{"name":"ice_nine","version":"0.11.2","platform":"ruby","checksum":"5d506a7d2723d5592dc121b9928e4931742730131f22a1a37649df1c1e2e63db"},
{"name":"imagen","version":"0.1.8","platform":"ruby","checksum":"fde7b727d4fe79c6bb5ac46c1f7184bf87a6d54df54d712ad2be039d2f93a162"},
{"name":"invisible_captcha","version":"2.0.0","platform":"ruby","checksum":"a381edcb1d1b8744e9dc398ecad142c3e2ab077604645f85eeb02f9ea535c042"},
{"name":"ipaddr","version":"1.2.2","platform":"ruby","checksum":"27916ee6367d549850d3675bc020f1f1ddafbbe1cfc58635f17dfa56c42f9f79"},
{"name":"ipaddr","version":"1.2.5","platform":"ruby","checksum":"4e679c71d6d8ed99f925487082f70f9a958de155591caa0e7f6cef9aa160f17a"},
{"name":"ipaddress","version":"0.8.3","platform":"ruby","checksum":"85640c4f9194c26937afc8c78e3074a8e7c97d5d1210358d1440f01034d006f5"},
{"name":"jaeger-client","version":"1.1.0","platform":"ruby","checksum":"cb5e9b9bbee6ee8d6a82d03d947a5b04543d8c0a949c22e484254f18d8a458a8"},
{"name":"jaro_winkler","version":"1.5.4","platform":"java","checksum":"0454333a50b44a09745878bfe57859893631ff7dfe48c029827894944514fe7c"},

View File

@ -819,7 +819,7 @@ GEM
parser (>= 2.5, != 2.5.1.1)
invisible_captcha (2.0.0)
rails (>= 5.0)
ipaddr (1.2.2)
ipaddr (1.2.5)
ipaddress (0.8.3)
jaeger-client (1.1.0)
opentracing (~> 0.3)
@ -1767,7 +1767,7 @@ DEPENDENCIES
httparty (~> 0.20.0)
icalendar
invisible_captcha (~> 2.0.0)
ipaddr (= 1.2.2)
ipaddr (~> 1.2.5)
ipaddress (~> 0.8.3)
ipynbdiff!
jira-ruby (~> 2.1.4)

View File

@ -6,7 +6,6 @@
@import './pages/hierarchy';
@import './pages/issues';
@import './pages/labels';
@import './pages/login';
@import './pages/merge_requests';
@import './pages/note_form';
@import './pages/notes';

View File

@ -1,4 +1,5 @@
@import 'framework/variables';
@import 'mixins_and_variables_and_functions';
/* Login Page */
.login-page {
.container {

View File

@ -756,222 +756,6 @@ input:-ms-input-placeholder {
svg {
fill: currentColor;
}
.login-page .container {
max-width: 960px;
}
.login-page .navbar-gitlab .container {
max-width: none;
}
.login-page .flash-container {
margin-bottom: 16px;
position: relative;
top: 8px;
}
.login-page .brand-holder {
font-size: 18px;
line-height: 1.5;
}
.login-page .brand-holder p {
font-size: 16px;
color: #888;
}
.login-page .brand-holder h3 {
font-size: 22px;
}
.login-page .brand-holder img {
max-width: 100%;
margin-bottom: 30px;
}
.login-page .brand-holder a {
font-weight: 600;
}
.login-page p {
font-size: 13px;
}
.login-page .signin-text p {
margin-bottom: 0;
line-height: 1.5;
}
.login-page .borderless .login-box,
.login-page .borderless .omniauth-container {
box-shadow: none;
}
.login-page .borderless .g-recaptcha > div {
margin-left: auto;
margin-right: auto;
}
.login-page .login-box,
.login-page .omniauth-container {
box-shadow: 0 0 0 1px #dcdcde;
border-radius: 0.25rem;
}
.login-page .login-box .login-heading h3,
.login-page .omniauth-container .login-heading h3 {
font-weight: 400;
line-height: 1.5;
margin: 0 0 10px;
}
.login-page .login-box .login-footer,
.login-page .omniauth-container .login-footer {
margin-top: 10px;
}
.login-page .login-box .login-footer p:last-child,
.login-page .omniauth-container .login-footer p:last-child {
margin-bottom: 0;
}
.login-page .login-box a.forgot,
.login-page .omniauth-container a.forgot {
float: right;
padding-top: 6px;
}
.login-page .login-box .nav .active a,
.login-page .omniauth-container .nav .active a {
background: transparent;
}
.login-page .login-box .login-body,
.login-page .omniauth-container .login-body {
font-size: 13px;
}
.login-page .login-box .login-body input + p,
.login-page .login-box .login-body input ~ p.field-validation,
.login-page .omniauth-container .login-body input + p,
.login-page .omniauth-container .login-body input ~ p.field-validation {
margin-top: 5px;
}
.login-page .login-box .login-body .username .validation-success,
.login-page .omniauth-container .login-body .username .validation-success {
color: #217645;
}
.login-page .login-box .login-body .username .validation-error,
.login-page .omniauth-container .login-body .username .validation-error {
color: #dd2b0e;
}
.login-page .omniauth-container {
border-radius: 0.25rem;
font-size: 13px;
}
.login-page .omniauth-container p {
margin: 0;
}
.login-page .omniauth-container form {
padding: 0;
border: 0;
background: none;
}
.login-page .new-session-tabs {
display: flex;
box-shadow: 0 0 0 1px #dcdcde;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
}
.login-page .new-session-tabs.nav-links-unboxed {
border-color: transparent;
box-shadow: none;
}
.login-page .new-session-tabs.nav-links-unboxed .nav-item {
border-left: 0;
border-right: 0;
border-bottom: 1px solid #dcdcde;
background-color: transparent;
}
.login-page .new-session-tabs.custom-provider-tabs {
flex-wrap: wrap;
}
.login-page .new-session-tabs.custom-provider-tabs li {
min-width: 85px;
flex-basis: auto;
}
.login-page .new-session-tabs.custom-provider-tabs li:nth-child(n + 5) {
border-top: 1px solid #dcdcde;
}
.login-page .new-session-tabs.custom-provider-tabs a {
font-size: 16px;
}
.login-page .new-session-tabs li {
flex: 1;
text-align: center;
border-left: 1px solid #dcdcde;
}
.login-page .new-session-tabs li:first-of-type {
border-left: 0;
border-top-left-radius: 4px;
}
.login-page .new-session-tabs li:last-of-type {
border-top-right-radius: 4px;
}
.login-page .new-session-tabs li:not(.active) {
background-color: #fbfafd;
}
.login-page .new-session-tabs li a {
width: 100%;
font-size: 18px;
}
.login-page .new-session-tabs li.active > a {
cursor: default;
}
.login-page .form-control:active,
.login-page .form-control:focus {
background-color: #fff;
}
.login-page .submit-container {
margin-top: 16px;
}
.login-page input[type="submit"] {
margin-bottom: 0;
display: block;
width: 100%;
}
.login-page .devise-errors h2 {
margin-top: 0;
font-size: 14px;
color: #ae1800;
}
@media (max-width: 575.98px) {
.login-page .col-md-5.float-right {
float: none !important;
margin-bottom: 45px;
}
}
.devise-layout-html {
margin: 0;
padding: 0;
height: 100%;
}
.devise-layout-html body {
height: calc(100% - 51px);
margin: 0;
padding: 0;
}
.devise-layout-html body.navless {
height: calc(100% - 11px);
}
.devise-layout-html body .page-wrap {
min-height: 100%;
position: relative;
}
.devise-layout-html body .footer-container,
.devise-layout-html body hr.footer-fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 40px;
background: #fff;
}
.devise-layout-html body .login-page-broadcast {
margin-top: 40px;
}
.devise-layout-html body .navless-container {
padding: 0 15px 65px;
}
.devise-layout-html body .flash-container {
padding-bottom: 65px;
}
@media (max-width: 575.98px) {
.devise-layout-html body .flash-container {
padding-bottom: 0;
}
}
.gl-display-flex {
display: flex;

View File

@ -5,7 +5,7 @@ module Types
class UserAchievementType < BaseObject
graphql_name 'UserAchievement'
authorize :read_achievement
authorize :read_user_achievement
field :id,
::Types::GlobalIDType[::Achievements::UserAchievement],

View File

@ -3,5 +3,10 @@
module Achievements
class UserAchievementPolicy < ::BasePolicy
delegate { @subject.achievement.namespace }
delegate { @subject.user }
rule { can?(:read_user_profile) | can?(:admin_achievement) }.enable :read_user_achievement
rule { ~can?(:read_achievement) }.prevent :read_user_achievement
end
end

View File

@ -1,4 +1,5 @@
- page_title _('Enter Admin Mode')
- add_page_specific_style 'page_bundles/login'
.row.justify-content-center
.col-md-5.new-session-forms-container

View File

@ -1,4 +1,5 @@
- page_title _('Enter 2FA for Admin Mode')
- add_page_specific_style 'page_bundles/login'
.row.justify-content-center
.col-md-5.new-session-forms-container

View File

@ -1,3 +1,4 @@
- add_page_specific_style 'page_bundles/login'
!!! 5
%html.devise-layout-html{ class: system_message_class }
= render "layouts/head", { startup_filename: 'signin' }

View File

@ -1,3 +1,4 @@
- add_page_specific_style 'page_bundles/login'
!!! 5
%html.devise-layout-html{ lang: "en", class: system_message_class }
= render "layouts/head"

View File

@ -1,6 +1,7 @@
!!! 5
%html.devise-layout-html.navless{ class: system_message_class }
- add_page_specific_style 'page_bundles/signup'
- add_page_specific_style 'page_bundles/login'
= render "layouts/head"
%body.signup-page{ class: "#{user_application_theme} #{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
= render "layouts/header/logo_with_title"

View File

@ -1,6 +1,7 @@
!!! 5
%html{ lang: "en" }
= render "layouts/head"
- add_page_specific_style 'page_bundles/login'
%body.login-page.application.navless{ class: user_application_theme, data: { page: body_data_page } }
= render "layouts/header/logo_with_title"
= render "layouts/broadcast"

View File

@ -1,6 +1,7 @@
- @html_class = "subscriptions-layout-html"
- page_title _('Your profile')
- add_page_specific_style 'page_bundles/signup'
- add_page_specific_style 'page_bundles/login'
- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"

View File

@ -51,7 +51,8 @@
.avatar-holder
= link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer' do
= render Pajamas::AvatarComponent.new(@user, alt: "", size: 96, avatar_options: { itemprop: "image" })
#js-user-achievements{ data: { root_url: root_url, user_id: @user.id } }
- if Ability.allowed?(current_user, :read_user_profile, @user)
#js-user-achievements{ data: { root_url: root_url, user_id: @user.id } }
.gl-display-inline-block.gl-vertical-align-top.gl-text-left.gl-max-w-80
- if @user.blocked? || !@user.confirmed?
.user-info

View File

@ -294,6 +294,7 @@ module Gitlab
config.assets.precompile << "page_bundles/jira_connect.css"
config.assets.precompile << "page_bundles/jira_connect_users.css"
config.assets.precompile << "page_bundles/learn_gitlab.css"
config.assets.precompile << "page_bundles/login.css"
config.assets.precompile << "page_bundles/marketing_popover.css"
config.assets.precompile << "page_bundles/members.css"
config.assets.precompile << "page_bundles/merge_conflicts.css"

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class FinalizeIssuesIidScopingToNamespace < Gitlab::Database::Migration[2.1]
MIGRATION = 'IssuesInternalIdScopeUpdater'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
ensure_batched_background_migration_is_finished(
job_class_name: MIGRATION,
table_name: :internal_ids,
column_name: :id,
job_arguments: [],
finalize: true)
end
def down; end
end

View File

@ -0,0 +1 @@
b0091fc76ead45dab7a0cd4d2b0a65858703cb18a98cca7715b88bceac8c2ed0

View File

@ -327,6 +327,7 @@ ETag
ETags
Etsy
Excon
exfiltrate
exfiltration
ExifTool
expirable

View File

@ -74,7 +74,7 @@ If you are coming to GitLab from another platform, the following information is
| Topic | Description |
|:----------------------------------------------------|:------------|
| [Importing to GitLab](user/project/import/index.md) | Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz, and SVN into GitLab. |
| [Migrating from SVN](user/project/import/svn.md) | Convert a SVN repository to Git and GitLab. |
| [Migrating from SVN](user/project/import/index.md#import-from-subversion) | Convert a SVN repository to Git and GitLab. |
## Build an integration with GitLab

View File

@ -617,6 +617,12 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
migration might take multiple hours or days to complete on larger GitLab instances. Make sure the migration
has completed successfully before upgrading to 15.7.0 or later.
- Due to [a bug introduced in GitLab 15.4](https://gitlab.com/gitlab-org/gitlab/-/issues/390155), if one or more Git repositories in Gitaly Cluster is [unavailable](../administration/gitaly/recovery.md#unavailable-repositories), then [Repository checks](../administration/repository_checks.md#repository-checks) and [Geo replication and verification](../administration/geo/index.md) stop running for all project or project wiki repositories in the affected Gitaly Cluster. The bug was fixed by [reverting the change in GitLab 15.9.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110823). Before upgrading to this version, check if you have any "unavailable" repositories. See [the bug issue](https://gitlab.com/gitlab-org/gitlab/-/issues/390155) for more information.
- A redesigned sign-in page is enabled by default in GitLab 15.4 and later, with improvements shipping in later releases. For more information, see [epic 8557](https://gitlab.com/groups/gitlab-org/-/epics/8557).
It can be disabled with a feature flag. Start [a Rails console](../administration/operations/rails_console.md) and run:
```ruby
Feature.disable(:restyle_login_page)
```
### 15.3.4

View File

@ -425,7 +425,8 @@ For more information, see
## Users with minimal access **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in GitLab 13.4.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in GitLab 13.4.
> - Support for inviting users with minimal access role [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106438) in GitLab 15.9.
Owners can add members with a "minimal access" role to a root group. Such users do not:

View File

@ -39,6 +39,20 @@ Keep in mind the limitations of [migrating using file exports](../settings/impor
When migrating from self-managed to GitLab.com, user associations (such as comment author)
are changed to the user who is importing the projects.
## Security
Only import projects from sources you trust. If you import a project from an untrusted source,
an attacker could steal your sensitive data. For example, an imported project
with a malicious `.gitlab-ci.yml` file could allow an attacker to exfiltrate group CI/CD variables.
GitLab self-managed administrators can reduce their attack surface by disabling import sources they don't need:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Scroll to **Import sources**.
1. Clear checkboxes for importers that are not required.
## Available project importers
You can import projects from:
@ -65,7 +79,7 @@ You can then [connect your external repository to get CI/CD benefits](../../../c
GitLab can not automatically migrate Subversion repositories to Git. Converting Subversion repositories to Git can be difficult, but several tools exist including:
- [`git svn`](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git), for very small and simple repositories.
- [`git svn`](https://git-scm.com/book/en/v2/Git-and-Other-Systems-Migrating-to-Git), for very small and basic repositories.
- [`reposurgeon`](http://www.catb.org/~esr/reposurgeon/repository-editing.html), for larger and more complex repositories.
## Migrate using the API
@ -82,10 +96,9 @@ over a series of Docker pulls and pushes. Re-run any CI pipelines to retrieve an
## Migrate between two self-managed GitLab instances
To migrate from an existing self-managed GitLab instance to a new self-managed GitLab instance, it's
best to [back up](../../../raketasks/backup_restore.md)
the existing instance and restore it on the new instance. For example, this is useful when migrating
a self-managed instance from an old server to a new server.
To migrate from an existing self-managed GitLab instance to a new self-managed GitLab instance,
you should [back up](../../../raketasks/backup_restore.md)
the existing instance and restore it on the new instance. For example, you could use this method to migrate a self-managed instance from an old server to a new server.
The backups produced don't depend on the operating system running GitLab. You can therefore use
the restore method to switch between different operating system distributions or versions, as long
@ -159,17 +172,3 @@ For more information, see:
including settings that need checking afterwards and other limitations.
For support, customers must enter into a paid engagement with GitLab Professional Services.
## Security
Only import projects from sources you trust. If you import a project from an untrusted source, it
may be possible for an attacker to steal your sensitive data. For example, an imported project
with a malicious `.gitlab-ci.yml` file could allow an attacker to exfiltrate group CI/CD variables.
GitLab self-managed administrators can reduce their attack surface by disabling import sources they don't need:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand **Visibility and access controls**.
1. Scroll to **Import sources**.
1. Clear checkboxes for importers that are not required.

View File

@ -12,11 +12,32 @@ module Gitlab
end
def match?(requested_ip, requested_port = nil)
return false unless ip.include?(requested_ip)
requested_ip = IPAddr.new(requested_ip) if requested_ip.is_a?(String)
return false unless ip_include?(requested_ip)
return true if port.nil?
port == requested_port
end
private
# Prior to ipaddr v1.2.3, if the allow list were the IPv4 to IPv6
# mapped address ::ffff:169.254.168.100 and the requested IP were
# 169.254.168.100 or ::ffff:169.254.168.100, the IP would be
# considered in the allow list. However, with
# https://github.com/ruby/ipaddr/pull/31, IPAddr#include? will
# only match if the IP versions are the same. This method
# preserves backwards compatibility if the versions differ by
# checking inclusion by coercing an IPv4 address to its IPv6
# mapped address.
def ip_include?(requested_ip)
return true if ip.include?(requested_ip)
return ip.include?(requested_ip.ipv4_mapped) if requested_ip.ipv4? && ip.ipv6?
return ip.ipv4_mapped.include?(requested_ip) if requested_ip.ipv6? && ip.ipv4?
false
end
end
end
end

View File

@ -1,4 +1,4 @@
import { GlEmptyState, GlTabs, GlTab, GlSprintf } from '@gitlab/ui';
import { GlEmptyState, GlModal, GlTabs, GlTab, GlSprintf } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@ -7,7 +7,7 @@ import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/alert';
import { stubComponent } from 'helpers/stub_component';
import AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import PackagesApp from '~/packages_and_registries/package_registry/pages/details.vue';
import DependencyRow from '~/packages_and_registries/package_registry/components/details/dependency_row.vue';
@ -66,6 +66,7 @@ describe('PackagesApp', () => {
};
const { __typename, ...packageWithoutTypename } = packageData();
const showMock = jest.fn();
function createComponent({
resolver = jest.fn().mockResolvedValue(packageDetailsQuery()),
@ -86,17 +87,11 @@ describe('PackagesApp', () => {
stubs: {
PackageTitle,
DeletePackages,
GlModal: {
template: `
<div>
<slot name="modal-title"></slot>
<p><slot></slot></p>
</div>
`,
GlModal: stubComponent(GlModal, {
methods: {
show: jest.fn(),
show: showMock,
},
},
}),
GlSprintf,
GlTabs,
GlTab,
@ -251,7 +246,7 @@ describe('PackagesApp', () => {
await findDeleteButton().trigger('click');
expect(findDeleteModal().find('p').text()).toBe(
expect(findDeleteModal().text()).toBe(
'You are about to delete version 1.0.0 of @gitlab-org/package-15. Are you sure?',
);
});
@ -331,13 +326,15 @@ describe('PackagesApp', () => {
await waitForPromises();
const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
expect(showDeletePackageSpy).not.toHaveBeenCalled();
expect(showDeleteFileSpy).toHaveBeenCalled();
expect(showMock).toHaveBeenCalledTimes(1);
await waitForPromises();
expect(findDeleteFileModal().text()).toBe(
'You are about to delete foo-1.0.1.tgz. This is a destructive action that may render your package unusable. Are you sure?',
);
});
it('when its the only file opens delete package confirmation modal', async () => {
@ -360,17 +357,13 @@ describe('PackagesApp', () => {
await waitForPromises();
const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
expect(showDeletePackageSpy).toHaveBeenCalled();
expect(showDeleteFileSpy).not.toHaveBeenCalled();
expect(showMock).toHaveBeenCalledTimes(1);
await waitForPromises();
expect(findDeleteModal().find('p').text()).toBe(
expect(findDeleteModal().text()).toBe(
'Deleting the last package asset will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
);
});
@ -542,15 +535,13 @@ describe('PackagesApp', () => {
await waitForPromises();
const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
findPackageFiles().vm.$emit('delete-files', packageFiles());
expect(showDeletePackageSpy).toHaveBeenCalled();
expect(showMock).toHaveBeenCalledTimes(1);
await waitForPromises();
expect(findDeleteModal().find('p').text()).toBe(
expect(findDeleteModal().text()).toBe(
'Deleting all package assets will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
);
});

View File

@ -20,5 +20,5 @@ RSpec.describe GitlabSchema.types['UserAchievement'], feature_category: :user_pr
it { expect(described_class.graphql_name).to eq('UserAchievement') }
it { expect(described_class).to have_graphql_fields(fields) }
it { expect(described_class).to require_graphql_authorizations(:read_achievement) }
it { expect(described_class).to require_graphql_authorizations(:read_user_achievement) }
end

View File

@ -2,7 +2,7 @@
require 'fast_spec_helper'
RSpec.describe Gitlab::UrlBlockers::IpAllowlistEntry do
RSpec.describe Gitlab::UrlBlockers::IpAllowlistEntry, feature_category: :integrations do
let(:ipv4) { IPAddr.new('192.168.1.1') }
describe '#initialize' do
@ -65,11 +65,31 @@ RSpec.describe Gitlab::UrlBlockers::IpAllowlistEntry do
end
it 'matches IPv6 within IPv6 range' do
ipv6_range = IPAddr.new('fd84:6d02:f6d8:c89e::/124')
ipv6_range = IPAddr.new('::ffff:192.168.1.0/8')
ip_allowlist_entry = described_class.new(ipv6_range)
expect(ip_allowlist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
expect(ip_allowlist_entry).not_to be_match('fd84:6d02:f6d8:f::f', 8080)
end
it 'matches IPv4 to IPv6 mapped addresses in allow list' do
ipv6_range = IPAddr.new('::ffff:192.168.1.1')
ip_allowlist_entry = described_class.new(ipv6_range)
expect(ip_allowlist_entry).to be_match(ipv4, 8080)
expect(ip_allowlist_entry).to be_match(ipv6_range.to_range.last.to_s, 8080)
expect(ip_allowlist_entry).not_to be_match('::ffff:192.168.1.0', 8080)
expect(ip_allowlist_entry).not_to be_match('::ffff:169.254.168.101', 8080)
end
it 'matches IPv4 to IPv6 mapped addresses in requested IP' do
ipv4_range = IPAddr.new('192.168.1.1/24')
ip_allowlist_entry = described_class.new(ipv4_range)
expect(ip_allowlist_entry).to be_match(ipv4, 8080)
expect(ip_allowlist_entry).to be_match('::ffff:192.168.1.0', 8080)
expect(ip_allowlist_entry).to be_match('::ffff:192.168.1.1', 8080)
expect(ip_allowlist_entry).not_to be_match('::ffff:169.254.170.100/8', 8080)
end
end
end

View File

@ -0,0 +1,72 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe FinalizeIssuesIidScopingToNamespace, :migration, feature_category: :team_planning do
let(:batched_migrations) { table(:batched_background_migrations) }
let!(:migration) { described_class::MIGRATION }
describe '#up' do
shared_examples 'finalizes the migration' do
it 'finalizes the migration' do
allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner) do |runner|
expect(runner).to receive(:finalize).with('"IssuesInternalIdScopeUpdater"', :internal_ids, :id, [nil, "up"])
end
end
end
context 'when migration is missing' do
it 'warns migration not found' do
expect(Gitlab::AppLogger)
.to receive(:warn).with(/Could not find batched background migration for the given configuration:/)
migrate!
end
end
context 'with migration present' do
let!(:migration) do
batched_migrations.create!(
job_class_name: 'IssuesInternalIdScopeUpdater',
table_name: :internal_ids,
column_name: :id,
job_arguments: [nil, 'up'],
interval: 2.minutes,
min_value: 1,
max_value: 2,
batch_size: 1000,
sub_batch_size: 200,
gitlab_schema: :gitlab_main,
status: 3 # finished
)
end
context 'when migration finished successfully' do
it 'does not raise exception' do
expect { migrate! }.not_to raise_error
end
end
context 'with different migration statuses' do
using RSpec::Parameterized::TableSyntax
where(:status, :description) do
0 | 'paused'
1 | 'active'
4 | 'failed'
5 | 'finalizing'
end
with_them do
before do
migration.update!(status: status)
end
it_behaves_like 'finalizes the migration'
end
end
end
end
end

View File

@ -0,0 +1,78 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Achievements::UserAchievementPolicy, feature_category: :user_profile do
let(:maintainer) { create(:user) }
let(:group) { create(:group, :public) }
let(:current_user) { create(:user) }
let(:achievement) { create(:achievement, namespace: group) }
let(:achievement_owner) { create(:user) }
let(:user_achievement) { create(:user_achievement, achievement: achievement, user: achievement_owner) }
before do
group.add_maintainer(maintainer)
end
subject { described_class.new(current_user, user_achievement) }
it 'is readable to everyone when user has public profile' do
is_expected.to be_allowed(:read_user_achievement)
end
context 'when user has private profile' do
before do
achievement_owner.update!(private_profile: true)
end
context 'for achievement owner' do
let(:current_user) { achievement_owner }
it 'is visible' do
is_expected.to be_allowed(:read_user_achievement)
end
end
context 'for group maintainer' do
let(:current_user) { maintainer }
it 'is visible' do
is_expected.to be_allowed(:read_user_achievement)
end
end
context 'for others' do
it 'is hidden' do
is_expected.not_to be_allowed(:read_user_achievement)
end
end
end
context 'when group is private' do
let(:group) { create(:group, :private) }
context 'for achievement owner' do
let(:current_user) { achievement_owner }
it 'is hidden' do
is_expected.not_to be_allowed(:read_user_achievement)
end
end
context 'for group maintainer' do
let(:current_user) { maintainer }
it 'is visible' do
is_expected.to be_allowed(:read_user_achievement)
end
end
context 'for others' do
it 'is hidden' do
is_expected.not_to be_allowed(:read_user_achievement)
end
end
end
end