Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-24 21:07:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-24 21:07:15 +0300
commitff8299c65d414ebd987dc68ac6035edb6340d412 (patch)
tree033af5898263b54e3a33e18e3aacee3cc3eb3140
parent8a37720edff0c74579bba2f8f985f37ed49ffa49 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/pages/sessions/new/index.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_alert.vue9
-rw-r--r--app/controllers/groups/application_controller.rb8
-rw-r--r--app/controllers/groups/group_members_controller.rb8
-rw-r--r--app/views/groups/_invite_members_modal.html.haml15
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/projects/_invite_members.html.haml2
-rw-r--r--app/views/projects/_invite_members_modal.html.haml15
-rw-r--r--app/views/projects/issues/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml2
-rw-r--r--app/views/shared/_confirm_your_email_alert.html.haml7
-rw-r--r--app/views/shared/issuable/_invite_members_trigger.html.haml8
-rw-r--r--doc/administration/database_load_balancing.md18
-rw-r--r--doc/api/packages/nuget.md29
-rw-r--r--doc/ci/README.md2
-rw-r--r--doc/user/gitlab_com/index.md7
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/features/users/login_spec.rb18
-rw-r--r--spec/frontend/vue_alerts_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/dismissible_alert_spec.js41
20 files changed, 141 insertions, 64 deletions
diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js
index d39f56cfd03..465aed88c01 100644
--- a/app/assets/javascripts/pages/sessions/new/index.js
+++ b/app/assets/javascripts/pages/sessions/new/index.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import initVueAlerts from '~/vue_alerts';
import NoEmojiValidator from '../../../emoji/no_emoji_validator';
import LengthValidator from './length_validator';
import OAuthRememberMe from './oauth_remember_me';
@@ -19,4 +20,5 @@ document.addEventListener('DOMContentLoaded', () => {
// Save the URL fragment from the current window location. This will be present if the user was
// redirected to sign-in after attempting to access a protected URL that included a fragment.
preserveUrlFragment(window.location.hash);
+ initVueAlerts();
});
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
index 8494f99fd7d..52371e42ba1 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
@@ -1,11 +1,14 @@
<script>
-/* eslint-disable vue/no-v-html */
-import { GlAlert } from '@gitlab/ui';
+import { GlAlert, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
export default {
+ name: 'DismissibleAlert',
components: {
GlAlert,
},
+ directives: {
+ SafeHtml,
+ },
props: {
html: {
type: String,
@@ -28,6 +31,6 @@ export default {
<template>
<gl-alert v-if="!isDismissed" v-bind="$attrs" @dismiss="dismiss" v-on="$listeners">
- <div v-html="html"></div>
+ <div v-safe-html="html"></div>
</gl-alert>
</template>
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index a3bbfc8be0d..f6c71ac8087 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -13,8 +13,16 @@ class Groups::ApplicationController < ApplicationController
before_action :set_sorting
requires_cross_project_access
+ helper_method :can_manage_members?
+
private
+ def can_manage_members?(group = @group)
+ strong_memoize(:can_manage_members) do
+ can?(current_user, :admin_group_member, group)
+ end
+ end
+
def group
@group ||= find_routable!(Group, params[:group_id] || params[:id])
end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 8d9059d271f..d5e7653dea2 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -22,8 +22,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
feature_category :authentication_and_authorization
- helper_method :can_manage_members?
-
def index
@sort = params[:sort].presence || sort_value_name
@@ -53,12 +51,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
private
- def can_manage_members?
- strong_memoize(:can_manage_members) do
- can?(current_user, :admin_group_member, @group)
- end
- end
-
def present_invited_members(invited_members)
present_members(invited_members
.page(params[:invited_members_page])
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index f4f3c8ce8f7..3be1a142ca6 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -1,7 +1,8 @@
-- if can?(current_user, :admin_group_member, group)
- .js-invite-members-modal{ data: { id: group.id,
- name: group.name,
- is_project: 'false',
- access_levels: GroupMember.access_level_roles.to_json,
- default_access_level: Gitlab::Access::GUEST,
- help_link: help_page_url('user/permissions') }.merge(group_select_data(group)) }
+- return unless can_manage_members?(group)
+
+.js-invite-members-modal{ data: { id: group.id,
+ name: group.name,
+ is_project: 'false',
+ access_levels: GroupMember.access_level_roles.to_json,
+ default_access_level: Gitlab::Access::GUEST,
+ help_link: help_page_url('user/permissions') }.merge(group_select_data(group)) }
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index 433337602f1..a302fa605e7 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -4,6 +4,8 @@
- flash.each do |key, value|
- if key == 'toast' && value
.js-toast-message{ data: { message: value } }
+ - elsif value == I18n.t('devise.failure.unconfirmed')
+ = render 'shared/confirm_your_email_alert'
- elsif value
%div{ class: "flash-#{key} mb-2" }
= sprite_icon(icons[key], css_class: 'align-middle mr-1') unless icons[key].nil?
diff --git a/app/views/projects/_invite_members.html.haml b/app/views/projects/_invite_members.html.haml
index ab630d34501..fc292da6fcf 100644
--- a/app/views/projects/_invite_members.html.haml
+++ b/app/views/projects/_invite_members.html.haml
@@ -9,4 +9,4 @@
event: 'click_button',
label: 'invite_members_empty_project' } }
-= render 'shared/issuable/invite_members_trigger', project: @project
+= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/projects/_invite_members_modal.html.haml b/app/views/projects/_invite_members_modal.html.haml
index 00f823b9016..5dd6ec0addf 100644
--- a/app/views/projects/_invite_members_modal.html.haml
+++ b/app/views/projects/_invite_members_modal.html.haml
@@ -1,7 +1,8 @@
-- if can_invite_members_for_project?(project)
- .js-invite-members-modal{ data: { id: project.id,
- name: project.name,
- is_project: 'true',
- access_levels: ProjectMember.access_level_roles.to_json,
- default_access_level: Gitlab::Access::GUEST,
- help_link: help_page_url('user/permissions') } }
+- return unless can_import_members?
+
+.js-invite-members-modal{ data: { id: project.id,
+ name: project.name,
+ is_project: 'true',
+ access_levels: ProjectMember.access_level_roles.to_json,
+ default_access_level: Gitlab::Access::GUEST,
+ help_link: help_page_url('user/permissions') } }
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index a465f59c559..6c6f98e0b20 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -4,4 +4,4 @@
- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
= render 'projects/issuable/show', issuable: @issue, api_awards_path: award_emoji_issue_api_path(@issue)
-= render 'shared/issuable/invite_members_trigger', project: @project
+= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 691ce8dc5fc..c4ee522bfa7 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -96,5 +96,5 @@
#js-review-bar
-= render 'shared/issuable/invite_members_trigger', project: @project
+= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/shared/_confirm_your_email_alert.html.haml b/app/views/shared/_confirm_your_email_alert.html.haml
new file mode 100644
index 00000000000..b9906a89ce4
--- /dev/null
+++ b/app/views/shared/_confirm_your_email_alert.html.haml
@@ -0,0 +1,7 @@
+.js-vue-alert{ 'v-cloak': true,
+ data: { dismissible: 'true',
+ title: _('Please confirm your email address'),
+ primary_button_text: _('Resend confirmation email'),
+ primary_button_link: new_user_confirmation_path,
+ variant: 'warning'} }
+ = (_("To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}") % { strongStart: '<strong>', strongEnd: '</strong>' }).html_safe
diff --git a/app/views/shared/issuable/_invite_members_trigger.html.haml b/app/views/shared/issuable/_invite_members_trigger.html.haml
deleted file mode 100644
index 5dd6ec0addf..00000000000
--- a/app/views/shared/issuable/_invite_members_trigger.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- return unless can_import_members?
-
-.js-invite-members-modal{ data: { id: project.id,
- name: project.name,
- is_project: 'true',
- access_levels: ProjectMember.access_level_roles.to_json,
- default_access_level: Gitlab::Access::GUEST,
- help_link: help_page_url('user/permissions') } }
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index e9f989c96ea..1c1066c8e12 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -31,7 +31,7 @@ sent to the primary (unless necessary), the primary (`db3`) hardly has any load.
## Requirements
-For load balancing to work you will need at least PostgreSQL 11 or newer,
+For load balancing to work, you need at least PostgreSQL 11 or newer,
[**MySQL is not supported**](../install/requirements.md#database). You also need to make sure that you have
at least 1 secondary in [hot standby](https://www.postgresql.org/docs/11/hot-standby.html) mode.
@@ -42,7 +42,7 @@ you should put a load balancer in front of every database, and have GitLab conne
to those load balancers.
For example, say you have a primary (`db1.gitlab.com`) and two secondaries,
-`db2.gitlab.com` and `db3.gitlab.com`. For this setup you will need to have 3
+`db2.gitlab.com` and `db3.gitlab.com`. For this setup, you need to have 3
load balancers, one for every host. For example:
- `primary.gitlab.com` forwards to `db1.gitlab.com`
@@ -56,7 +56,7 @@ means forwarding should now happen as follows:
- `secondary1.gitlab.com` forwards to `db1.gitlab.com`
- `secondary2.gitlab.com` forwards to `db3.gitlab.com`
-GitLab does not take care of this for you, so you will need to do so yourself.
+GitLab does not take care of this for you, so you need to do so yourself.
Finally, load balancing requires that GitLab can connect to all hosts using the
same credentials and port as configured in the
@@ -72,7 +72,7 @@ different ports or credentials for different hosts is not supported.
## Enabling load balancing
For the environment in which you want to use load balancing, you'll need to add
-the following. This will balance the load between `host1.example.com` and
+the following. This balances the load between `host1.example.com` and
`host2.example.com`.
**In Omnibus installations:**
@@ -176,15 +176,15 @@ The following options can be set:
| `disconnect_timeout` | The time in seconds after which an old connection is closed, after the list of hosts was updated. | 120 |
| `use_tcp` | Lookup DNS resources using TCP instead of UDP | false |
-If `record_type` is set to `SRV`, GitLab will continue to use a round-robin algorithm
-and will ignore the `weight` and `priority` in the record. Since SRV records usually
-return hostnames instead of IPs, GitLab will look for the IPs of returned hostnames
+If `record_type` is set to `SRV`, then GitLab continues to use round-robin algorithm
+and ignores the `weight` and `priority` in the record. Since SRV records usually
+return hostnames instead of IPs, GitLab needs to look for the IPs of returned hostnames
in the additional section of the SRV response. If no IP is found for a hostname, GitLab
-will query the configured `nameserver` for ANY record for each such hostname looking for A or AAAA
+needs to query the configured `nameserver` for ANY record for each such hostname looking for A or AAAA
records, eventually dropping this hostname from rotation if it can't resolve its IP.
The `interval` value specifies the _minimum_ time between checks. If the A
-record has a TTL greater than this value, then service discovery will honor said
+record has a TTL greater than this value, then service discovery honors said
TTL. For example, if the TTL of the A record is 90 seconds, then service
discovery waits at least 90 seconds before checking the A record again.
diff --git a/doc/api/packages/nuget.md b/doc/api/packages/nuget.md
index bbcb2cb9bc4..d19e2dfa65b 100644
--- a/doc/api/packages/nuget.md
+++ b/doc/api/packages/nuget.md
@@ -102,6 +102,30 @@ curl --request PUT \
"https://gitlab.example.com/api/v4/projects/1/packages/nuget"
```
+## Upload a symbol package file
+
+> Introduced in GitLab 12.8.
+
+Upload a NuGet symbol package file (`.snupkg`):
+
+```plaintext
+PUT projects/:id/packages/nuget/symbolpackage
+```
+
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `id` | string | yes | The ID or full path of the project. |
+| `package_name` | string | yes | The name of the package. |
+| `package_version` | string | yes | The version of the package. |
+| `package_filename`| string | yes | The name of the file. |
+
+```shell
+curl --request PUT \
+ --upload-file path/to/mynugetpkg.1.3.0.17.snupkg \
+ --user <username>:<personal_access_token> \
+ "https://gitlab.example.com/api/v4/projects/1/packages/nuget/symbolpackage"
+```
+
## Route prefix
For the remaining routes, there are two sets of identical routes that each make requests in
@@ -193,6 +217,11 @@ Example response:
"@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget",
"@type": "PackagePublish/2.0.0",
"comment": "Push and delete (or unlist) packages."
+ },
+ {
+ "@id": "https://gitlab.example.com/api/v4/projects/1/packages/nuget/symbolpackage",
+ "@type": "SymbolPackagePublish/4.9.0",
+ "comment": "Push symbol packages."
}
]
}
diff --git a/doc/ci/README.md b/doc/ci/README.md
index dc4312250ca..c58e02d08d7 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -144,7 +144,7 @@ See also:
Learn more about:
-- [Why you might chose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/).
+- [Why you might choose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/).
- [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/).
- [5 Teams that made the switch to GitLab CI/CD](https://about.gitlab.com/blog/2019/04/25/5-teams-that-made-the-switch-to-gitlab-ci-cd/)
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 332a62bb092..00dee5ee489 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -39,6 +39,13 @@ and has its own dedicated IP address (`192.237.158.143`).
The IP address for `mg.gitlab.com` is subject to change at any time.
+### Service Desk custom mailbox
+
+On GitLab.com there's a mailbox configured for Service Desk with the email adress:
+`contact-project+%{key}@incoming.gitlab.com`. To use this mailbox, configure the
+[custom suffix](../project/service_desk.md#configuring-a-custom-email-address-suffix) in project
+settings.
+
## Backups
[See our backup strategy](https://about.gitlab.com/handbook/engineering/infrastructure/production/#backups).
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f5fe7462f29..81ec7baa924 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -24290,6 +24290,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please confirm your email address"
+msgstr ""
+
msgid "Please contact an admin to register runners."
msgstr ""
@@ -33895,6 +33898,9 @@ msgstr ""
msgid "To connect an SVN repository, check out %{svn_link}."
msgstr ""
+msgid "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select %{strongStart}Resend confirmation email.%{strongEnd}"
+msgstr ""
+
msgid "To define internal users, first enable new users set to external"
msgstr ""
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 7010059a7ff..6c38d5d8b24 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -97,6 +97,8 @@ RSpec.describe 'Login' do
describe 'with an unconfirmed email address' do
let!(:user) { create(:user, confirmed_at: nil) }
let(:grace_period) { 2.days }
+ let(:alert_title) { 'Please confirm your email address' }
+ let(:alert_message) { "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select Resend confirmation email" }
before do
stub_application_setting(send_user_confirmation_email: true)
@@ -109,13 +111,14 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).not_to have_content(I18n.t('devise.failure.unconfirmed'))
+ expect(page).not_to have_content(alert_title)
+ expect(page).not_to have_content(alert_message)
expect(page).not_to have_link('Resend confirmation email', href: new_user_confirmation_path)
end
end
context 'when the confirmation grace period is expired' do
- it 'prevents the user from logging in and renders a resend confirmation email link' do
+ it 'prevents the user from logging in and renders a resend confirmation email link', :js do
travel_to((grace_period + 1.day).from_now) do
expect(authentication_metrics)
.to increment(:user_unauthenticated_counter)
@@ -123,7 +126,8 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).to have_content(I18n.t('devise.failure.unconfirmed'))
+ expect(page).to have_content(alert_title)
+ expect(page).to have_content(alert_message)
expect(page).to have_link('Resend confirmation email', href: new_user_confirmation_path)
end
end
@@ -889,6 +893,8 @@ RSpec.describe 'Login' do
context 'when sending confirmation email and not yet confirmed' do
let!(:user) { create(:user, confirmed_at: nil) }
let(:grace_period) { 2.days }
+ let(:alert_title) { 'Please confirm your email address' }
+ let(:alert_message) { "To continue, you need to select the link in the confirmation email we sent to verify your email address. If you didn't get our email, select Resend confirmation email" }
before do
stub_application_setting(send_user_confirmation_email: true)
@@ -906,7 +912,7 @@ RSpec.describe 'Login' do
end
context "when not having confirmed within Devise's allow_unconfirmed_access_for time" do
- it 'does not allow login and shows a flash alert to confirm the email address' do
+ it 'does not allow login and shows a flash alert to confirm the email address', :js do
travel_to((grace_period + 1.day).from_now) do
expect(authentication_metrics)
.to increment(:user_unauthenticated_counter)
@@ -915,7 +921,9 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
expect(current_path).to eq new_user_session_path
- expect(page).to have_content(I18n.t('devise.failure.unconfirmed'))
+ expect(page).to have_content(alert_title)
+ expect(page).to have_content(alert_message)
+ expect(page).to have_link('Resend confirmation email', href: new_user_confirmation_path)
end
end
end
diff --git a/spec/frontend/vue_alerts_spec.js b/spec/frontend/vue_alerts_spec.js
index 05b73415544..30be606292f 100644
--- a/spec/frontend/vue_alerts_spec.js
+++ b/spec/frontend/vue_alerts_spec.js
@@ -28,8 +28,8 @@ describe('VueAlerts', () => {
alerts
.map(
(x) => `
- <div class="js-vue-alert"
- data-dismissible="${x.dismissible}"
+ <div class="js-vue-alert"
+ data-dismissible="${x.dismissible}"
data-title="${x.title}"
data-primary-button-text="${x.primaryButtonText}"
data-primary-button-link="${x.primaryButtonLink}"
diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
index cfa6d1064e5..fcd004d35a7 100644
--- a/spec/frontend/vue_shared/components/dismissible_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
@@ -5,18 +5,12 @@ import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
const TEST_HTML = 'Hello World! <strong>Foo</strong>';
describe('vue_shared/components/dismissible_alert', () => {
- const testAlertProps = {
- primaryButtonText: 'Lorem ipsum',
- primaryButtonLink: '/lorem/ipsum',
- };
-
let wrapper;
const createComponent = (props = {}) => {
wrapper = shallowMount(DismissibleAlert, {
propsData: {
html: TEST_HTML,
- ...testAlertProps,
...props,
},
});
@@ -28,16 +22,13 @@ describe('vue_shared/components/dismissible_alert', () => {
const findAlert = () => wrapper.find(GlAlert);
- describe('with default', () => {
+ describe('default', () => {
beforeEach(() => {
createComponent();
});
it('shows alert', () => {
- const alert = findAlert();
-
- expect(alert.exists()).toBe(true);
- expect(alert.props()).toEqual(expect.objectContaining(testAlertProps));
+ expect(findAlert().exists()).toBe(true);
});
it('shows given HTML', () => {
@@ -54,4 +45,32 @@ describe('vue_shared/components/dismissible_alert', () => {
});
});
});
+
+ describe('with additional props', () => {
+ const testAlertProps = {
+ dismissible: true,
+ title: 'Mock Title',
+ primaryButtonText: 'Lorem ipsum',
+ primaryButtonLink: '/lorem/ipsum',
+ variant: 'warning',
+ };
+
+ beforeEach(() => {
+ createComponent(testAlertProps);
+ });
+
+ it('passes other props', () => {
+ expect(findAlert().props()).toEqual(expect.objectContaining(testAlertProps));
+ });
+ });
+
+ describe('with unsafe HTML', () => {
+ beforeEach(() => {
+ createComponent({ html: '<a onclick="alert("XSS")">Link</a>' });
+ });
+
+ it('removes unsafe HTML', () => {
+ expect(findAlert().html()).toContain('<a>Link</a>');
+ });
+ });
});