Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-07-26 18:11:45 +00:00
parent 60a260df41
commit 013a89081d
21 changed files with 370 additions and 330 deletions

View file

@ -1,5 +1,5 @@
<script>
import { MEMBER_TYPES } from '../../constants';
import { MEMBER_TYPES, EE_ACTION_BUTTONS } from 'ee_else_ce/members/constants';
import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue';
import GroupActionButtons from '../action_buttons/group_action_buttons.vue';
import InviteActionButtons from '../action_buttons/invite_action_buttons.vue';
@ -12,6 +12,8 @@ export default {
GroupActionButtons,
InviteActionButtons,
AccessRequestActionButtons,
BannedActionButtons: () =>
import('ee_component/members/components/action_buttons/banned_action_buttons.vue'),
},
props: {
member: {
@ -42,6 +44,7 @@ export default {
[MEMBER_TYPES.group]: 'group-action-buttons',
[MEMBER_TYPES.invite]: 'invite-action-buttons',
[MEMBER_TYPES.accessRequest]: 'access-request-action-buttons',
...EE_ACTION_BUTTONS,
};
return dictionary[this.memberType];

View file

@ -9,6 +9,8 @@ export const EE_APP_OPTIONS = {};
// Overridden in EE
export const EE_TABS = [];
export const EE_ACTION_BUTTONS = {};
export const FIELD_KEY_ACCOUNT = 'account';
export const FIELD_KEY_SOURCE = 'source';
export const FIELD_KEY_GRANTED = 'granted';

View file

@ -171,7 +171,7 @@ module IssuableActions
discussions = Discussion.build_collection(notes, issuable)
if issuable.is_a?(MergeRequest)
render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { discussion_cache_context }, context: self)
render_mr_discussions(discussions, discussion_serializer, discussion_cache_context)
elsif issuable.is_a?(Issue)
render json: discussion_serializer.represent(discussions, context: self) if stale?(etag: [discussion_cache_context, discussions])
else
@ -182,6 +182,24 @@ module IssuableActions
private
def render_mr_discussions(discussions, serializer, cache_context)
if Feature.enabled?(:mr_discussions_http_cache, project)
return unless stale?(etag: [cache_context, discussions])
if Feature.enabled?(:disabled_mr_discussions_redis_cache, project)
render json: serializer.represent(discussions, context: self)
else
render_cached_discussions(discussions, serializer, cache_context)
end
else
render_cached_discussions(discussions, serializer, cache_context)
end
end
def render_cached_discussions(discussions, serializer, cache_context)
render_cached(discussions, with: serializer, cache_context: -> (_) { cache_context }, context: self)
end
def paginated_discussions
return if params[:per_page].blank?
return if issuable.instance_of?(MergeRequest) && Feature.disabled?(:paginated_mr_discussions, project)

View file

@ -14,7 +14,7 @@ module Resolvers
response = ::ErrorTracking::IssueDetailsService.new(
project,
current_user,
{ issue_id: id.model_id }
{ issue_id: id.model_id, tracking_event: :error_tracking_view_details }
).execute
issue = response[:issue]
issue.gitlab_project = project if issue

View file

@ -182,7 +182,7 @@ module GroupsHelper
def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false)
link_to(group_path(group), class: "group-path #{'breadcrumb-item-text' unless for_dropdown} js-breadcrumb-item-text #{'hidable' if hidable}") do
icon = group_icon(group, class: "avatar-tile", width: 15, height: 15) if (group.try(:avatar_url) || show_avatar) && !Rails.env.test?
icon = group_icon(group, alt: group.name, class: "avatar-tile", width: 15, height: 15) if group.try(:avatar_url) || show_avatar
[icon, simple_sanitize(group.name)].join.html_safe
end
end

View file

@ -0,0 +1,8 @@
---
name: disabled_mr_discussions_redis_cache
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92752
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368366
milestone: '15.3'
type: development
group: group::code review
default_enabled: false

View file

@ -0,0 +1,8 @@
---
name: mr_discussions_http_cache
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92752
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368363
milestone: '15.3'
type: development
group: group::code review
default_enabled: false

View file

@ -56,6 +56,7 @@ exceptions:
- DML
- DNS
- DOM
- DORA
- DSA
- DSL
- DVCS

View file

@ -17,20 +17,6 @@ Troubleshooting Elasticsearch requires:
- Knowledge of common terms.
- Establishing within which category the problem fits.
## Common terminology
- **Lucene**: A full-text search library written in Java.
- **Near real time (NRT)**: Refers to the slight latency from the time to index a
document to the time when it becomes searchable.
- **Cluster**: A collection of one or more nodes that work together to hold all
the data, providing indexing and search capabilities.
- **Node**: A single server that works as part of a cluster.
- **Index**: A collection of documents that have somewhat similar characteristics.
- **Document**: A basic unit of information that can be indexed.
- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
a Lucene index.
- **Replicas**: Failover mechanisms that duplicate indices.
## Troubleshooting workflows
The type of problem will determine what steps to take. The possible troubleshooting workflows are for:

View file

@ -150,10 +150,10 @@ Dockerfiles to build and deploy <https://docs.gitlab.com>. It is heavily inspire
| Dockerfile | Docker image | Description |
|:---------------------------------------------------------------------------------------------------------------------------|:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch) |
| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
| [`bootstrap.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/bootstrap.Dockerfile) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
| [`builder.onbuild.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/builder.onbuild.Dockerfile) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
| [`nginx.onbuild.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/nginx.onbuild.Dockerfile) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch) |
| [`archives.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/archives.Dockerfile) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
### How to build the images

View file

@ -1116,6 +1116,36 @@ include a visual representation to help readers understand it, you can:
an area of the screen.
- Create a short video of the interaction and link to it.
## Emojis
Don't use the Markdown emoji format, for example `:smile:`, for any purpose. Use
[GitLab SVG icons](#gitlab-svg-icons) instead.
Use of emoji in Markdown requires GitLab Flavored Markdown, which is not supported by Kramdown,
the Markdown rendering engine used for GitLab documentation.
## GitLab SVG icons
> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) in GitLab 12.7.
You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/)
directly in the documentation. For example, `**{tanuki}**` renders as: **{tanuki}**.
In most cases, you should avoid using the icons in text.
However, you can use an icon when hover text is the only
available way to describe a UI element. For example, **Delete** or **Edit** buttons
often have hover text only.
When you do use an icon, start with the hover text and follow it with the SVG reference in parentheses.
- Avoid: `Select **{pencil}** **Edit**.` This generates as: Select **{pencil}** **Edit**.
- Use instead: `Select **Edit** (**{pencil}**).` This generates as: Select **Edit** (**{pencil}**).
Do not use words to describe the icon:
- Avoid: `Select **Erase job log** (the trash icon).`
- Use instead: `Select **Erase job log** (**{remove}**).` This generates as: Select **Erase job log** (**{remove}**).
## Videos
Adding GitLab YouTube video tutorials to the documentation is highly
@ -1197,28 +1227,6 @@ different mobile devices.
`/help`, because the GitLab Markdown processor doesn't support iframes. It's
hidden on the documentation site, but is displayed by `/help`.
## GitLab SVG icons
> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) in GitLab 12.7.
You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/)
directly in the documentation. For example, `**{tanuki}**` renders as: **{tanuki}**.
In most cases, you should avoid using the icons in text.
However, you can use an icon when hover text is the only
available way to describe a UI element. For example, **Delete** or **Edit** buttons
often have hover text only.
When you do use an icon, start with the hover text and follow it with the SVG reference in parentheses.
- Avoid: `Select **{pencil}** **Edit**.` This generates as: Select **{pencil}** **Edit**.
- Use instead: `Select **Edit** (**{pencil}**).` This generates as: Select **Edit** (**{pencil}**).
Do not use words to describe the icon:
- Avoid: `Select **Erase job log** (the trash icon).`
- Use instead: `Select **Erase job log** (**{remove}**).` This generates as: Select **Erase job log** (**{remove}**).
## Alert boxes
Use alert boxes to call attention to information. Use them sparingly, and never have an alert box immediately follow another alert box.

View file

@ -24,6 +24,20 @@ integration are logs. The most relevant logs for this integration are:
Here are some common pitfalls and how to overcome them.
## Common terminology
- **Lucene**: A full-text search library written in Java.
- **Near real time (NRT)**: Refers to the slight latency from the time to index a
document to the time when it becomes searchable.
- **Cluster**: A collection of one or more nodes that work together to hold all
the data, providing indexing and search capabilities.
- **Node**: A single server that works as part of a cluster.
- **Index**: A collection of documents that have somewhat similar characteristics.
- **Document**: A basic unit of information that can be indexed.
- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
a Lucene index.
- **Replicas**: Failover mechanisms that duplicate indices.
## How can I verify that my GitLab instance is using Elasticsearch?
There are a couple of ways to achieve that:

View file

@ -700,101 +700,21 @@ The results are stored in `gl-container-scanning-report.json`.
## Reports JSON format
The container scanning tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
The container scanning tool emits JSON reports which the [GitLab Runner](https://docs.gitlab.com/runner/)
recognizes through the [`artifacts:reports`](../../../ci/yaml/#artifactsreports)
keyword in the CI configuration file.
Here's an example container scanning report:
Once the CI job finishes, the Runner uploads these reports to GitLab, which are then available in
the CI Job artifacts. In GitLab Ultimate, these reports can be viewed in the corresponding [pipeline](../vulnerability_report/pipeline.md)
and become part of the [Vulnerability Report](../vulnerability_report/).
```json-doc
{
"version": "14.0.0",
"vulnerabilities": [
{
"id": "df52bc8ce9a2ae56bbcb0c4ecda62123fbd6f69b",
"category": "container_scanning",
"message": "CVE-2019-3462 in apt-1.4.8",
"description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.",
"severity": "High",
"confidence": "Unknown",
"solution": "Upgrade apt from 1.4.8 to 1.4.9",
"scanner": {
"id": "trivy",
"name": "trivy"
},
"location": {
"dependency": {
"package": {
"name": "apt"
},
"version": "1.4.8"
},
"operating_system": "debian:9.4",
"image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e",
"default_branch_image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0:latest"
},
"identifiers": [
{
"type": "cve",
"name": "CVE-2019-3462",
"value": "CVE-2019-3462",
"url": "http://www.securityfocus.com/bid/106690"
}
],
"links": [
{
"url": "http://www.securityfocus.com/bid/106690"
},
{
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3462"
},
{
"url": "https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E"
},
{
"url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00013.html"
},
{
"url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00014.html"
},
{
"url": "https://security.netapp.com/advisory/ntap-20190125-0002/"
},
{
"url": "https://usn.ubuntu.com/3863-1/"
},
{
"url": "https://usn.ubuntu.com/3863-2/"
},
{
"url": "https://usn.ubuntu.com/usn/usn-3863-1"
},
{
"url": "https://usn.ubuntu.com/usn/usn-3863-2"
},
{
"url": "https://www.debian.org/security/2019/dsa-4371"
}
]
}
],
"remediations": []
"scan": {
"scanner": {
"id": "trivy",
"name": "Trivy",
"url": "https://github.com/aquasecurity/trivy/",
"vendor": {
"name": "GitLab"
},
"version": "0.16.0"
},
"type": "container_scanning",
"start_time": "2021-04-14T19:45:58",
"end_time": "2021-04-14T19:46:18",
"status": "success"
}
}
```
These reports must follow a format defined in the
[security report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/). See:
- [Latest schema for the container scanning report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
- [Example container scanning report](https://gitlab.com/gitlab-examples/security/security-reports/-/blob/master/samples/container-scanning.json)
For more information, see [Security scanner integration](../../../development/integrations/secure.md).
## Security Dashboard

View file

@ -41349,6 +41349,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
msgid "Unban"
msgstr ""
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr ""
@ -42167,6 +42170,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
msgid "User was successfully unbanned."
msgstr ""
msgid "User was successfully updated."
msgstr ""

View file

@ -113,7 +113,7 @@
"dateformat": "^5.0.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
"dompurify": "^2.3.9",
"dompurify": "^2.3.10",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^10.0.0",

View file

@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe GroupsHelper do
include ApplicationHelper
include AvatarsHelper
describe '#group_icon_url' do
it 'returns an url for the avatar' do
@ -135,6 +136,37 @@ RSpec.describe GroupsHelper do
end
end
describe '#group_title_link' do
let_it_be(:group) { create(:group, :with_avatar) }
let(:raw_link) { group_title_link(group, show_avatar: true) }
let(:document) { Nokogiri::HTML.parse(raw_link) }
describe 'link' do
subject(:link) { document.css('.group-path').first }
it 'uses the group name as innerText' do
expect(link.inner_text).to eq(group.name)
end
it 'links to the group path' do
expect(link.attr('href')).to eq(group_path(group))
end
end
describe 'icon' do
subject(:icon) { document.css('.avatar-tile').first }
it 'specifies the group name as the alt text' do
expect(icon.attr('alt')).to eq(group.name)
end
it 'uses the group\'s avatar_url' do
expect(icon.attr('src')).to eq(group.avatar_url)
end
end
end
describe '#share_with_group_lock_help_text' do
context 'traversal queries' do
let_it_be_with_reload(:root_group) { create(:group) }

View file

@ -87,7 +87,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
context 'when IP is already banned' do
subject { gl_auth.find_for_git_client('username', 'password', project: nil, ip: 'ip') }
subject { gl_auth.find_for_git_client('username-does-not-matter', 'password-does-not-matter', project: nil, ip: 'ip') }
before do
expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter|
@ -219,16 +219,16 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it 'recognizes master passwords' do
user = create(:user, password: 'password')
user = create(:user)
expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
end
include_examples 'user login operation with unique ip limit' do
let(:user) { create(:user, password: 'password') }
let(:user) { create(:user) }
def operation
expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
end
end
@ -502,8 +502,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user = create(
:user,
:blocked,
username: 'normal_user',
password: 'my-secret'
username: 'normal_user'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@ -512,7 +511,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when 2fa is enabled globally' do
let_it_be(:user) do
create(:user, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
create(:user, username: 'normal_user', otp_grace_period_started_at: 1.day.ago)
end
before do
@ -536,7 +535,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when 2fa is enabled personally' do
let(:user) do
create(:user, :two_factor, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
create(:user, :two_factor, username: 'normal_user', otp_grace_period_started_at: 1.day.ago)
end
it 'fails' do
@ -548,8 +547,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'goes through lfs authentication' do
user = create(
:user,
username: 'normal_user',
password: 'my-secret'
username: 'normal_user'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@ -559,8 +557,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'goes through oauth authentication when the username is oauth2' do
user = create(
:user,
username: 'oauth2',
password: 'my-secret'
username: 'oauth2'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@ -635,7 +632,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when deploy token and user have the same username' do
let(:username) { 'normal_user' }
let(:user) { create(:user, username: username, password: 'my-secret') }
let(:user) { create(:user, username: username) }
let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) }
it 'succeeds for the token' do
@ -648,7 +645,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'succeeds for the user' do
auth_success = { actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities }
expect(gl_auth.find_for_git_client(username, 'my-secret', project: project, ip: 'ip'))
expect(gl_auth.find_for_git_client(username, user.password, project: project, ip: 'ip'))
.to have_attributes(auth_success)
end
end
@ -834,72 +831,64 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
describe 'find_with_user_password' do
let!(:user) do
create(:user,
username: username,
password: password,
password_confirmation: password)
end
let!(:user) { create(:user, username: username) }
let(:username) { 'John' } # username isn't lowercase, test this
let(:password) { 'my-secret' }
it "finds user by valid login/password" do
expect(gl_auth.find_with_user_password(username, password)).to eql user
expect(gl_auth.find_with_user_password(username, user.password)).to eql user
end
it 'finds user by valid email/password with case-insensitive email' do
expect(gl_auth.find_with_user_password(user.email.upcase, password)).to eql user
expect(gl_auth.find_with_user_password(user.email.upcase, user.password)).to eql user
end
it 'finds user by valid username/password with case-insensitive username' do
expect(gl_auth.find_with_user_password(username.upcase, password)).to eql user
expect(gl_auth.find_with_user_password(username.upcase, user.password)).to eql user
end
it "does not find user with invalid password" do
password = 'wrong'
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
expect(gl_auth.find_with_user_password(username, 'incorrect_password')).not_to eql user
end
it "does not find user with invalid login" do
user = 'wrong'
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
username = 'wrong'
expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
include_examples 'user login operation with unique ip limit' do
def operation
expect(gl_auth.find_with_user_password(username, password)).to eq(user)
expect(gl_auth.find_with_user_password(username, user.password)).to eq(user)
end
end
it 'finds the user in deactivated state' do
user.deactivate!
expect(gl_auth.find_with_user_password(username, password)).to eql user
expect(gl_auth.find_with_user_password(username, user.password)).to eql user
end
it "does not find user in blocked state" do
user.block
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it 'does not find user in locked state' do
user.lock_access!
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it "does not find user in ldap_blocked state" do
user.ldap_block
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it 'does not find user in blocked_pending_approval state' do
user.block_pending_approval
expect(gl_auth.find_with_user_password(username, password)).not_to eql user
expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
context 'with increment_failed_attempts' do
@ -917,7 +906,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user.save!
expect do
gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
gl_auth.find_with_user_password(username, user.password, increment_failed_attempts: true)
user.reload
end.to change(user, :failed_attempts).from(2).to(0)
end
@ -946,7 +935,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user.save!
expect do
gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
gl_auth.find_with_user_password(username, user.password, increment_failed_attempts: true)
user.reload
end.not_to change(user, :failed_attempts)
end
@ -961,7 +950,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it "tries to autheticate with db before ldap" do
expect(Gitlab::Auth::Ldap::Authentication).not_to receive(:login)
expect(gl_auth.find_with_user_password(username, password)).to eq(user)
expect(gl_auth.find_with_user_password(username, user.password)).to eq(user)
end
it "does not find user by using ldap as fallback to for authentication" do
@ -983,7 +972,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it "does not find user by valid login/password" do
expect(gl_auth.find_with_user_password(username, password)).to be_nil
expect(gl_auth.find_with_user_password(username, user.password)).to be_nil
end
context "with ldap enabled" do
@ -992,7 +981,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it "does not find non-ldap user by valid login/password" do
expect(gl_auth.find_with_user_password(username, password)).to be_nil
expect(gl_auth.find_with_user_password(username, user.password)).to be_nil
end
end
end

View file

@ -34,6 +34,8 @@ RSpec.describe 'getting a detailed sentry error' do
context 'when data is loading via reactive cache' do
before do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
post_graphql(query, current_user: current_user)
end
@ -48,6 +50,10 @@ RSpec.describe 'getting a detailed sentry error' do
.to receive(:issue_details)
.and_return({ issue: sentry_detailed_error })
expect(Gitlab::UsageDataCounters::HLLRedisCounter)
.to receive(:track_event)
.with('error_tracking_view_details', values: current_user.id)
post_graphql(query, current_user: current_user)
end

View file

@ -16,9 +16,16 @@ RSpec.describe 'merge requests discussions' do
login_as(user)
end
# rubocop:disable RSpec/InstanceVariable
def send_request
get discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid)
get(
discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid),
headers: { 'If-None-Match' => @etag }
)
@etag = response.etag
end
# rubocop:enable RSpec/InstanceVariable
it 'returns 200' do
send_request
@ -63,11 +70,6 @@ RSpec.describe 'merge requests discussions' do
let!(:award_emoji) { create(:award_emoji, awardable: first_note) }
let!(:author_membership) { project.add_maintainer(author) }
before do
# Make a request to cache the discussions
send_request
end
shared_examples 'cache miss' do
it 'does not hit a warm cache' do
expect_next_instance_of(DiscussionSerializer) do |serializer|
@ -80,176 +82,213 @@ RSpec.describe 'merge requests discussions' do
end
end
it 'gets cached on subsequent requests' do
expect_next_instance_of(DiscussionSerializer) do |serializer|
expect(serializer).not_to receive(:represent)
end
shared_examples 'cache hit' do
it 'gets cached on subsequent requests' do
expect_next_instance_of(DiscussionSerializer) do |serializer|
expect(serializer).not_to receive(:represent)
end
send_request
end
context 'when a note in a discussion got updated' do
before do
first_note.update!(updated_at: 1.minute.from_now)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
send_request
end
end
context 'when a note in a discussion got its reference state updated' do
context 'when mr_discussions_http_cache and disabled_mr_discussions_redis_cache are enabled' do
before do
reference.close!
send_request
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
it_behaves_like 'cache hit'
context 'when a note in a discussion got resolved' do
before do
travel_to(1.minute.from_now) do
first_note.resolve!(user)
context 'when a note in a discussion got updated' do
before do
first_note.update!(updated_at: 1.minute.from_now)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when a note in a discussion got its reference state updated' do
before do
reference.close!
end
context 'when a note is added to a discussion' do
let!(:third_note) { create(:diff_note_on_merge_request, in_reply_to: first_note, noteable: merge_request, project: project) }
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note, third_note] }
end
end
context 'when a note is removed from a discussion' do
before do
second_note.destroy!
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note] }
end
end
context 'when an emoji is awarded to a note in discussion' do
before do
travel_to(1.minute.from_now) do
create(:award_emoji, awardable: first_note)
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when a note in a discussion got resolved' do
before do
travel_to(1.minute.from_now) do
first_note.resolve!(user)
end
end
context 'when an award emoji is removed from a note in discussion' do
before do
travel_to(1.minute.from_now) do
award_emoji.destroy!
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
context 'when a note is added to a discussion' do
let!(:third_note) { create(:diff_note_on_merge_request, in_reply_to: first_note, noteable: merge_request, project: project) }
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note, third_note] }
end
end
context 'when a note is removed from a discussion' do
before do
second_note.destroy!
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note] }
end
end
context 'when an emoji is awarded to a note in discussion' do
before do
travel_to(1.minute.from_now) do
create(:award_emoji, awardable: first_note)
end
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when an award emoji is removed from a note in discussion' do
before do
travel_to(1.minute.from_now) do
award_emoji.destroy!
end
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when the diff note position changes' do
before do
# This replicates a position change wherein timestamps aren't updated
# which is why `Gitlab::Timeless.timeless` is utilized. This is the
# same approach being used in Discussions::UpdateDiffPositionService
# which is responsible for updating the positions of diff discussions
# when MR updates.
first_note.position = Gitlab::Diff::Position.new(
old_path: first_note.position.old_path,
new_path: first_note.position.new_path,
old_line: first_note.position.old_line,
new_line: first_note.position.new_line + 1,
diff_refs: first_note.position.diff_refs
)
Gitlab::Timeless.timeless(first_note, &:save)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when the HEAD diff note position changes' do
before do
# This replicates a DiffNotePosition change. This is the same approach
# being used in Discussions::CaptureDiffNotePositionService which is
# responsible for updating/creating DiffNotePosition of a diff discussions
# in relation to HEAD diff.
new_position = Gitlab::Diff::Position.new(
old_path: first_note.position.old_path,
new_path: first_note.position.new_path,
old_line: first_note.position.old_line,
new_line: first_note.position.new_line + 1,
diff_refs: first_note.position.diff_refs
)
DiffNotePosition.create_or_update_for(
first_note,
diff_type: :head,
position: new_position,
line_code: 'bd4b7bfff3a247ccf6e3371c41ec018a55230bcc_534_521'
)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when author detail changes' do
before do
author.update!(name: "#{author.name} (Updated)")
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when author status changes' do
before do
Users::SetStatusService.new(author, message: "updated status").execute
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when author role changes' do
before do
Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(author_membership)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when current_user role changes' do
before do
Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(project.member(user))
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
end
context 'when the diff note position changes' do
context 'when mr_discussions_http_cache is disabled' do
before do
# This replicates a position change wherein timestamps aren't updated
# which is why `Gitlab::Timeless.timeless` is utilized. This is the
# same approach being used in Discussions::UpdateDiffPositionService
# which is responsible for updating the positions of diff discussions
# when MR updates.
first_note.position = Gitlab::Diff::Position.new(
old_path: first_note.position.old_path,
new_path: first_note.position.new_path,
old_line: first_note.position.old_line,
new_line: first_note.position.new_line + 1,
diff_refs: first_note.position.diff_refs
)
Gitlab::Timeless.timeless(first_note, &:save)
stub_feature_flags(mr_discussions_http_cache: false)
send_request
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
it_behaves_like 'cache hit'
end
context 'when the HEAD diff note position changes' do
context 'when disabled_mr_discussions_redis_cache is disabled' do
before do
# This replicates a DiffNotePosition change. This is the same approach
# being used in Discussions::CaptureDiffNotePositionService which is
# responsible for updating/creating DiffNotePosition of a diff discussions
# in relation to HEAD diff.
new_position = Gitlab::Diff::Position.new(
old_path: first_note.position.old_path,
new_path: first_note.position.new_path,
old_line: first_note.position.old_line,
new_line: first_note.position.new_line + 1,
diff_refs: first_note.position.diff_refs
)
DiffNotePosition.create_or_update_for(
first_note,
diff_type: :head,
position: new_position,
line_code: 'bd4b7bfff3a247ccf6e3371c41ec018a55230bcc_534_521'
)
stub_feature_flags(disabled_mr_discussions_redis_cache: false)
send_request
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
it_behaves_like 'cache hit'
end
context 'when author detail changes' do
context 'when mr_discussions_http_cache and disabled_mr_discussions_redis_cache are disabled' do
before do
author.update!(name: "#{author.name} (Updated)")
stub_feature_flags(mr_discussions_http_cache: false, disabled_mr_discussions_redis_cache: false)
send_request
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when author status changes' do
before do
Users::SetStatusService.new(author, message: "updated status").execute
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when author role changes' do
before do
Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(author_membership)
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
end
context 'when current_user role changes' do
before do
Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(project.member(user))
end
it_behaves_like 'cache miss' do
let(:changed_notes) { [first_note, second_note] }
end
it_behaves_like 'cache hit'
end
end
end

View file

@ -9001,9 +9001,9 @@ tapable@^1.0.0, tapable@^1.1.3:
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^6.0.2:
version "6.1.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"

View file

@ -5076,10 +5076,10 @@ dompurify@2.3.6:
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
dompurify@^2.3.9:
version "2.3.9"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.9.tgz#a4be5e7278338d6db09922dffcf6182cd099d70a"
integrity sha512-3zOnuTwup4lPV/GfGS6UzG4ub9nhSYagR/5tB3AvDEwqyy5dtyCM2dVjwGDCnrPerXifBKTYh/UWCGKK7ydhhw==
dompurify@^2.3.10, dompurify@^2.3.9:
version "2.3.10"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385"
integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==
domutils@^2.5.2, domutils@^2.6.0:
version "2.6.0"
@ -12007,9 +12007,9 @@ tapable@^1.0.0, tapable@^1.1.3:
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^6.0.2:
version "6.0.5"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"