Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1323c36872
commit
aeaaaaf074
17 changed files with 174 additions and 56 deletions
|
@ -15,7 +15,7 @@ initFilePickers();
|
|||
new Group(); // eslint-disable-line no-new
|
||||
|
||||
function initNewGroupCreation(el) {
|
||||
const { hasErrors } = el.dataset;
|
||||
const { hasErrors, verificationRequired, verificationFormUrl, subscriptionsUrl } = el.dataset;
|
||||
|
||||
const props = {
|
||||
hasErrors: parseBoolean(hasErrors),
|
||||
|
@ -23,6 +23,11 @@ function initNewGroupCreation(el) {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
provide: {
|
||||
verificationRequired: parseBoolean(verificationRequired),
|
||||
verificationFormUrl,
|
||||
subscriptionsUrl,
|
||||
},
|
||||
render(h) {
|
||||
return h(NewGroupCreationApp, { props });
|
||||
},
|
||||
|
|
|
@ -10,10 +10,17 @@ export default {
|
|||
GlIcon,
|
||||
WelcomePage,
|
||||
LegacyContainer,
|
||||
CreditCardVerification: () =>
|
||||
import('ee_component/pages/groups/new/components/credit_card_verification.vue'),
|
||||
},
|
||||
directives: {
|
||||
SafeHtml,
|
||||
},
|
||||
inject: {
|
||||
verificationRequired: {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
@ -41,6 +48,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
activePanelName: null,
|
||||
verificationCompleted: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -67,6 +75,10 @@ export default {
|
|||
{ text: this.activePanel.title, href: `#${this.activePanel.name}` },
|
||||
];
|
||||
},
|
||||
|
||||
shouldVerify() {
|
||||
return this.verificationRequired && !this.verificationCompleted;
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
|
@ -93,12 +105,16 @@ export default {
|
|||
localStorage.setItem(this.persistenceKey, this.activePanelName);
|
||||
}
|
||||
},
|
||||
onVerified() {
|
||||
this.verificationCompleted = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<welcome-page v-if="!activePanelName" :panels="panels" :title="title">
|
||||
<credit-card-verification v-if="shouldVerify" @verified="onVerified" />
|
||||
<welcome-page v-else-if="!activePanelName" :panels="panels" :title="title">
|
||||
<template #footer>
|
||||
<slot name="welcome-footer"> </slot>
|
||||
</template>
|
||||
|
|
|
@ -134,6 +134,16 @@ module GroupsHelper
|
|||
@group_projects_sort || @sort || params[:sort] || sort_value_recently_created
|
||||
end
|
||||
|
||||
def verification_for_group_creation_data
|
||||
# overridden in EE
|
||||
{}
|
||||
end
|
||||
|
||||
def require_verification_for_group_creation_enabled?
|
||||
# overridden in EE
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false)
|
||||
|
|
|
@ -780,6 +780,10 @@ class Group < Namespace
|
|||
crm_settings&.enabled?
|
||||
end
|
||||
|
||||
def shared_with_group_links_visible_to_user(user)
|
||||
shared_with_group_links.preload_shared_with_groups.filter { |link| Ability.allowed?(user, :read_group, link.shared_with_group) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def max_member_access(user_ids)
|
||||
|
|
|
@ -14,7 +14,7 @@ class GroupGroupLink < ApplicationRecord
|
|||
presence: true
|
||||
|
||||
scope :non_guests, -> { where('group_access > ?', Gitlab::Access::GUEST) }
|
||||
scope :public_or_visible_to_user, ->(group, user) { where(shared_group: group, shared_with_group: Group.public_or_visible_to_user(user)) } # rubocop:disable Cop/GroupPublicOrVisibleToUser
|
||||
scope :preload_shared_with_groups, -> { preload(:shared_with_group) }
|
||||
|
||||
def self.access_options
|
||||
Gitlab::Access.options_with_owner
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
.group-edit-container.gl-mt-5
|
||||
|
||||
.js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s } }
|
||||
.js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(verification_for_group_creation_data) }
|
||||
|
||||
.row{ 'v-cloak': true }
|
||||
#create-group-pane.tab-pane
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: require_verification_for_group_creation
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77569
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349857
|
||||
milestone: '14.7'
|
||||
type: experiment
|
||||
group: group::activation
|
||||
default_enabled: false
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
# Audit event streaming **(ULTIMATE)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
|
||||
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
|
||||
> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available. To hide the feature per group, ask an administrator to [disable the feature flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. On GitLab.com, this feature is available.
|
||||
|
|
|
@ -965,7 +965,7 @@ However, some projects may fail to be migrated for different reasons.
|
|||
To verify that all projects have been migrated successfully, you can manually run the migration:
|
||||
|
||||
```shell
|
||||
gitlab-rake gitlab:pages:migrate_legacy_storage
|
||||
sudo gitlab-rake gitlab:pages:migrate_legacy_storage
|
||||
```
|
||||
|
||||
It's safe to interrupt this task and run it multiple times.
|
||||
|
|
|
@ -394,9 +394,9 @@ the roulette is not available, choose someone else from that list.
|
|||
|
||||
It is the responsibility of the author for the merge request to be reviewed. If it stays in the `ready for review` state too long it is recommended to request a review from a specific reviewer.
|
||||
|
||||
#### List of merge requests ready for review
|
||||
### Volunteering to review
|
||||
|
||||
Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name%5B%5D=workflow%3A%3Aready%20for%20review) and add themselves as a reviewer for any merge request they want to review.
|
||||
GitLab engineers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?state=opened&label_name%5B%5D=workflow%3A%3Aready%20for%20review) and add themselves as a reviewer for any merge request they want to review.
|
||||
|
||||
### Reviewing a merge request
|
||||
|
||||
|
@ -522,9 +522,12 @@ If the MR source branch is more than 1,000 commits behind the target branch:
|
|||
or check with the contributor first when they're actively working on the MR.
|
||||
- The rebase can usually be done inside GitLab with the `/rebase` [quick action](../user/project/quick_actions.md).
|
||||
|
||||
#### Taking over a community merge request
|
||||
|
||||
When an MR needs further changes but the author is not responding for a long period of time,
|
||||
or unable to finish the MR, we can take it over in accordance with our
|
||||
[Closing policy for issues and merge requests](contributing/#closing-policy-for-issues-and-merge-requests):
|
||||
or is unable to finish the MR, GitLab can take it over in accordance with our
|
||||
[Closing policy for issues and merge requests](contributing/#closing-policy-for-issues-and-merge-requests).
|
||||
A GitLab engineer (generally the merge request coach) will:
|
||||
|
||||
1. Add a comment to their MR saying you'll take it over to be able to get it merged.
|
||||
1. Add the label `~"coach will finish"` to their MR.
|
||||
|
|
|
@ -1035,10 +1035,8 @@ The on-demand DAST scan runs and the project's dashboard shows the results.
|
|||
To run a saved on-demand scan:
|
||||
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Security & Compliance > Configuration**.
|
||||
1. Select **Manage DAST scans**.
|
||||
1. In the **DAST Profiles** row, select **Manage**.
|
||||
1. Select the **Saved Scans** tab.
|
||||
1. On the left sidebar, select **Security & Compliance > On-demand Scans**.
|
||||
1. Select the **Scan library** tab.
|
||||
1. In the scan's row, select **Run scan**.
|
||||
|
||||
If the branch saved in the scan no longer exists, you must first
|
||||
|
@ -1074,27 +1072,23 @@ To schedule a scan:
|
|||
|
||||
To list saved on-demand scans:
|
||||
|
||||
1. From your project's home page, go to **Security & Compliance > Configuration**.
|
||||
1. Select the **Saved Scans** tab.
|
||||
1. From your project's home page, go to **Security & Compliance > On-demand Scans**.
|
||||
1. Select the **Scan library** tab.
|
||||
|
||||
#### View details of an on-demand scan
|
||||
|
||||
To view details of an on-demand scan:
|
||||
|
||||
1. From your project's home page, go to **Security & Compliance > Configuration**.
|
||||
1. Select **Manage DAST scans**.
|
||||
1. Select **Manage** in the **DAST Profiles** row.
|
||||
1. Select the **Saved Scans** tab.
|
||||
1. From your project's home page, go to **Security & Compliance > On-demand Scans**.
|
||||
1. Select the **Scan library** tab.
|
||||
1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Edit**.
|
||||
|
||||
#### Edit an on-demand scan
|
||||
|
||||
To edit an on-demand scan:
|
||||
|
||||
1. From your project's home page, go to **Security & Compliance > Configuration**.
|
||||
1. Select **Manage DAST scans**.
|
||||
1. Select **Manage** in the **DAST Profiles** row.
|
||||
1. Select the **Saved Scans** tab.
|
||||
1. From your project's home page, go to **Security & Compliance > On-demand Scans**.
|
||||
1. Select the **Scan library** tab.
|
||||
1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Edit**.
|
||||
1. Edit the form.
|
||||
1. Select **Save scan**.
|
||||
|
@ -1103,10 +1097,8 @@ To edit an on-demand scan:
|
|||
|
||||
To delete an on-demand scan:
|
||||
|
||||
1. From your project's home page, go to **Security & Compliance > Configuration**.
|
||||
1. Select **Manage DAST scans**.
|
||||
1. Select **Manage** in the **DAST Profiles** row.
|
||||
1. Select the **Saved Scans** tab.
|
||||
1. From your project's home page, go to **Security & Compliance > On-demand Scans**.
|
||||
1. Select the **Scan library** tab.
|
||||
1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Delete**.
|
||||
1. Select **Delete** to confirm the deletion.
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ To purge files from a GitLab repository:
|
|||
|
||||
Refer to the Git [`replace`](https://git-scm.com/book/en/v2/Git-Tools-Replace) documentation for information on how this works.
|
||||
|
||||
1. Run a [repository cleanup](#repository-cleanup).
|
||||
1. Wait at least 30 minutes, because the repository cleanup process only processes object older than 30 minutes.
|
||||
1. Run [repository cleanup](#repository-cleanup).
|
||||
|
||||
## Repository cleanup
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ module API
|
|||
module Entities
|
||||
class GroupDetail < Group
|
||||
expose :shared_with_groups do |group, options|
|
||||
SharedGroupWithGroup.represent(group.shared_with_group_links.public_or_visible_to_user(group, options[:current_user]))
|
||||
SharedGroupWithGroup.represent(group.shared_with_group_links_visible_to_user(options[:current_user]))
|
||||
end
|
||||
expose :runners_token, if: lambda { |group, options| options[:user_can_admin_group] }
|
||||
expose :prevent_sharing_groups_outside_hierarchy, if: ->(group) { group.root? }
|
||||
|
|
|
@ -17841,6 +17841,12 @@ msgstr ""
|
|||
msgid "Identities"
|
||||
msgstr ""
|
||||
|
||||
msgid "IdentityVerification|Before you create your group, we need you to verify your identity with a valid payment method."
|
||||
msgstr ""
|
||||
|
||||
msgid "IdentityVerification|Verify your identity"
|
||||
msgstr ""
|
||||
|
||||
msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -29,32 +29,6 @@ RSpec.describe GroupGroupLink do
|
|||
])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.public_or_visible_to_user' do
|
||||
let!(:user_with_access) { create :user }
|
||||
let!(:user_without_access) { create :user }
|
||||
let!(:shared_with_group) { create :group, :private }
|
||||
let!(:shared_group) { create :group }
|
||||
let!(:private_group_group_link) { create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_group) }
|
||||
|
||||
before do
|
||||
shared_group.add_owner(user_with_access)
|
||||
shared_group.add_owner(user_without_access)
|
||||
shared_with_group.add_developer(user_with_access)
|
||||
end
|
||||
|
||||
context 'when user can access shared group' do
|
||||
it 'returns the private group' do
|
||||
expect(described_class.public_or_visible_to_user(shared_group, user_with_access)).to include(private_group_group_link)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user does not have access to shared group' do
|
||||
it 'does not return private group' do
|
||||
expect(described_class.public_or_visible_to_user(shared_group, user_without_access)).not_to include(private_group_group_link)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validation' do
|
||||
|
|
|
@ -2859,4 +2859,55 @@ RSpec.describe Group do
|
|||
expect(described_class.get_ids_by_ids_or_paths([new_group_id], [group_path])).to match_array([group_id, new_group_id])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#shared_with_group_links_visible_to_user' do
|
||||
let_it_be(:admin) { create :admin }
|
||||
let_it_be(:normal_user) { create :user }
|
||||
let_it_be(:user_with_access) { create :user }
|
||||
let_it_be(:user_with_parent_access) { create :user }
|
||||
let_it_be(:user_without_access) { create :user }
|
||||
let_it_be(:shared_group) { create :group }
|
||||
let_it_be(:parent_group) { create :group, :private }
|
||||
let_it_be(:shared_with_private_group) { create :group, :private, parent: parent_group }
|
||||
let_it_be(:shared_with_internal_group) { create :group, :internal }
|
||||
let_it_be(:shared_with_public_group) { create :group, :public }
|
||||
let_it_be(:private_group_group_link) { create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_private_group) }
|
||||
let_it_be(:internal_group_group_link) { create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_internal_group) }
|
||||
let_it_be(:public_group_group_link) { create(:group_group_link, shared_group: shared_group, shared_with_group: shared_with_public_group) }
|
||||
|
||||
before do
|
||||
shared_with_private_group.add_developer(user_with_access)
|
||||
parent_group.add_developer(user_with_parent_access)
|
||||
end
|
||||
|
||||
context 'when user is admin', :enable_admin_mode do
|
||||
it 'returns all existing shared group links' do
|
||||
expect(shared_group.shared_with_group_links_visible_to_user(admin)).to contain_exactly(private_group_group_link, internal_group_group_link, public_group_group_link)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is nil' do
|
||||
it 'returns only link of public shared group' do
|
||||
expect(shared_group.shared_with_group_links_visible_to_user(nil)).to contain_exactly(public_group_group_link)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has no access to private shared group' do
|
||||
it 'returns links of internal and public shared groups' do
|
||||
expect(shared_group.shared_with_group_links_visible_to_user(normal_user)).to contain_exactly(internal_group_group_link, public_group_group_link)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is member of private shared group' do
|
||||
it 'returns links of private, internal and public shared groups' do
|
||||
expect(shared_group.shared_with_group_links_visible_to_user(user_with_access)).to contain_exactly(private_group_group_link, internal_group_group_link, public_group_group_link)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is inherited member of private shared group' do
|
||||
it 'returns links of private, internal and public shared groups' do
|
||||
expect(shared_group.shared_with_group_links_visible_to_user(user_with_parent_access)).to contain_exactly(private_group_group_link, internal_group_group_link, public_group_group_link)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -801,6 +801,54 @@ RSpec.describe API::Groups do
|
|||
expect(json_response['shared_projects'].count).to eq(limit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a group is shared', :aggregate_failures do
|
||||
let_it_be(:shared_group) { create(:group) }
|
||||
let_it_be(:group2_sub) { create(:group, :private, parent: group2) }
|
||||
let_it_be(:group_link_1) { create(:group_group_link, shared_group: shared_group, shared_with_group: group1) }
|
||||
let_it_be(:group_link_2) { create(:group_group_link, shared_group: shared_group, shared_with_group: group2_sub) }
|
||||
|
||||
subject(:shared_with_groups) { json_response['shared_with_groups'].map { _1['group_id']} }
|
||||
|
||||
context 'when authenticated as admin' do
|
||||
it 'returns all groups that share the group' do
|
||||
get api("/groups/#{shared_group.id}", admin)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(shared_with_groups).to contain_exactly(group_link_1.shared_with_group_id, group_link_2.shared_with_group_id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'returns only public groups that share the group' do
|
||||
get api("/groups/#{shared_group.id}")
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(shared_with_groups).to contain_exactly(group_link_1.shared_with_group_id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated as a member of a parent group that has shared the group' do
|
||||
it 'returns private group if direct member' do
|
||||
group2_sub.add_guest(user3)
|
||||
|
||||
get api("/groups/#{shared_group.id}", user3)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(shared_with_groups).to contain_exactly(group_link_1.shared_with_group_id, group_link_2.shared_with_group_id)
|
||||
end
|
||||
|
||||
it 'returns private group if inherited member' do
|
||||
inherited_guest_member = create(:user)
|
||||
group2.add_guest(inherited_guest_member)
|
||||
|
||||
get api("/groups/#{shared_group.id}", inherited_guest_member)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(shared_with_groups).to contain_exactly(group_link_1.shared_with_group_id, group_link_2.shared_with_group_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /groups/:id' do
|
||||
|
|
Loading…
Reference in a new issue