Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8f6e28e5
Commit
8f6e28e5
authored
Oct 01, 2020
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
8f122839
53db7654
Changes
72
Hide whitespace changes
Inline
Side-by-side
Showing
72 changed files
with
847 additions
and
117 deletions
+847
-117
app/assets/javascripts/ide/components/file_templates/dropdown.vue
...ts/javascripts/ide/components/file_templates/dropdown.vue
+3
-2
app/assets/javascripts/lib/utils/datetime_utility.js
app/assets/javascripts/lib/utils/datetime_utility.js
+19
-0
app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
.../vue_shared/components/dropdown/dropdown_search_input.vue
+5
-0
app/assets/javascripts/vue_shared/components/file_finder/index.vue
...s/javascripts/vue_shared/components/file_finder/index.vue
+5
-6
app/assets/stylesheets/pages/diff.scss
app/assets/stylesheets/pages/diff.scss
+0
-4
app/finders/group_members_finder.rb
app/finders/group_members_finder.rb
+19
-9
app/graphql/mutations/base_mutation.rb
app/graphql/mutations/base_mutation.rb
+1
-0
app/graphql/mutations/ci/base.rb
app/graphql/mutations/ci/base.rb
+6
-1
app/graphql/mutations/design_management/move.rb
app/graphql/mutations/design_management/move.rb
+8
-1
app/graphql/resolvers/base_resolver.rb
app/graphql/resolvers/base_resolver.rb
+1
-0
app/graphql/types/global_id_type.rb
app/graphql/types/global_id_type.rb
+16
-0
app/graphql/types/query_type.rb
app/graphql/types/query_type.rb
+12
-3
app/helpers/groups/group_members_helper.rb
app/helpers/groups/group_members_helper.rb
+1
-1
app/models/group.rb
app/models/group.rb
+9
-0
app/models/user.rb
app/models/user.rb
+2
-0
app/views/admin/groups/show.html.haml
app/views/admin/groups/show.html.haml
+1
-1
changelogs/unreleased/220203-gitlab-com-sso-create-no-access-role-fe-changes.yml
...20203-gitlab-com-sso-create-no-access-role-fe-changes.yml
+5
-0
changelogs/unreleased/mw-replace-fa-search-icons.yml
changelogs/unreleased/mw-replace-fa-search-icons.yml
+5
-0
config/feature_flags/licensed/minimal_access_role.yml
config/feature_flags/licensed/minimal_access_role.yml
+7
-0
doc/development/api_graphql_styleguide.md
doc/development/api_graphql_styleguide.md
+14
-0
ee/app/assets/javascripts/audit_events/components/audit_events_app.vue
.../javascripts/audit_events/components/audit_events_app.vue
+5
-5
ee/app/assets/javascripts/audit_events/components/date_range_buttons.vue
...avascripts/audit_events/components/date_range_buttons.vue
+59
-0
ee/app/assets/javascripts/audit_events/components/date_range_field.vue
.../javascripts/audit_events/components/date_range_field.vue
+34
-8
ee/app/assets/javascripts/audit_events/components/sorting_field.vue
...ets/javascripts/audit_events/components/sorting_field.vue
+1
-1
ee/app/assets/javascripts/audit_events/constants.js
ee/app/assets/javascripts/audit_events/constants.js
+4
-0
ee/app/assets/javascripts/boards/components/boards_list_selector/list_filter.vue
...ts/boards/components/boards_list_selector/list_filter.vue
+1
-1
ee/app/assets/stylesheets/components/audit_logs/sorting_field.scss
...sets/stylesheets/components/audit_logs/sorting_field.scss
+13
-5
ee/app/controllers/ee/admin/groups_controller.rb
ee/app/controllers/ee/admin/groups_controller.rb
+9
-0
ee/app/finders/ee/group_members_finder.rb
ee/app/finders/ee/group_members_finder.rb
+15
-0
ee/app/graphql/ee/mutations/boards/issues/issue_move_list.rb
ee/app/graphql/ee/mutations/boards/issues/issue_move_list.rb
+8
-4
ee/app/graphql/ee/types/project_type.rb
ee/app/graphql/ee/types/project_type.rb
+4
-1
ee/app/graphql/ee/types/query_type.rb
ee/app/graphql/ee/types/query_type.rb
+15
-3
ee/app/graphql/mutations/clusters/agent_tokens/create.rb
ee/app/graphql/mutations/clusters/agent_tokens/create.rb
+6
-2
ee/app/graphql/mutations/clusters/agent_tokens/delete.rb
ee/app/graphql/mutations/clusters/agent_tokens/delete.rb
+6
-2
ee/app/graphql/mutations/clusters/agents/delete.rb
ee/app/graphql/mutations/clusters/agents/delete.rb
+6
-2
ee/app/graphql/mutations/dast_on_demand_scans/create.rb
ee/app/graphql/mutations/dast_on_demand_scans/create.rb
+9
-0
ee/app/graphql/mutations/dast_scanner_profiles/delete.rb
ee/app/graphql/mutations/dast_scanner_profiles/delete.rb
+7
-1
ee/app/graphql/mutations/dast_scanner_profiles/update.rb
ee/app/graphql/mutations/dast_scanner_profiles/update.rb
+5
-1
ee/app/graphql/mutations/dast_site_profiles/delete.rb
ee/app/graphql/mutations/dast_site_profiles/delete.rb
+4
-0
ee/app/graphql/mutations/dast_site_profiles/update.rb
ee/app/graphql/mutations/dast_site_profiles/update.rb
+4
-1
ee/app/graphql/mutations/vulnerabilities/confirm.rb
ee/app/graphql/mutations/vulnerabilities/confirm.rb
+3
-0
ee/app/graphql/mutations/vulnerabilities/resolve.rb
ee/app/graphql/mutations/vulnerabilities/resolve.rb
+3
-0
ee/app/models/ee/group.rb
ee/app/models/ee/group.rb
+15
-0
ee/app/models/ee/group_member.rb
ee/app/models/ee/group_member.rb
+9
-1
ee/app/models/ee/user.rb
ee/app/models/ee/user.rb
+22
-0
ee/app/models/saml_provider.rb
ee/app/models/saml_provider.rb
+11
-1
ee/app/presenters/ee/group_member_presenter.rb
ee/app/presenters/ee/group_member_presenter.rb
+7
-0
ee/app/services/dast_site_profiles/update_service.rb
ee/app/services/dast_site_profiles/update_service.rb
+1
-1
ee/app/services/fetch_subscription_plans_service.rb
ee/app/services/fetch_subscription_plans_service.rb
+5
-1
ee/app/views/groups/saml_providers/_form.html.haml
ee/app/views/groups/saml_providers/_form.html.haml
+1
-1
ee/changelogs/unreleased/223260-improve-and-limit-date-filters.yml
...logs/unreleased/223260-improve-and-limit-date-filters.yml
+5
-0
ee/config/feature_flags/development/subscription_plan_cache_key.yml
...feature_flags/development/subscription_plan_cache_key.yml
+7
-0
ee/lib/ee/gitlab/access.rb
ee/lib/ee/gitlab/access.rb
+13
-3
ee/spec/finders/ee/group_members_finder_spec.rb
ee/spec/finders/ee/group_members_finder_spec.rb
+31
-0
ee/spec/frontend/audit_events/components/__snapshots__/audit_events_app_spec.js.snap
...ts/components/__snapshots__/audit_events_app_spec.js.snap
+5
-5
ee/spec/frontend/audit_events/components/date_range_buttons_spec.js
...ontend/audit_events/components/date_range_buttons_spec.js
+68
-0
ee/spec/frontend/audit_events/components/date_range_field_spec.js
...frontend/audit_events/components/date_range_field_spec.js
+62
-22
ee/spec/frontend/boards/components/board_list_selector/list_filter_spec.js
...boards/components/board_list_selector/list_filter_spec.js
+1
-1
ee/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
...ec/graphql/mutations/clusters/agent_tokens/create_spec.rb
+1
-1
ee/spec/graphql/mutations/clusters/agent_tokens/delete_spec.rb
...ec/graphql/mutations/clusters/agent_tokens/delete_spec.rb
+1
-1
ee/spec/graphql/mutations/clusters/agents/delete_spec.rb
ee/spec/graphql/mutations/clusters/agents/delete_spec.rb
+3
-3
ee/spec/models/group_member_spec.rb
ee/spec/models/group_member_spec.rb
+44
-0
ee/spec/models/group_spec.rb
ee/spec/models/group_spec.rb
+1
-1
ee/spec/models/saml_provider_spec.rb
ee/spec/models/saml_provider_spec.rb
+36
-0
ee/spec/models/user_spec.rb
ee/spec/models/user_spec.rb
+50
-0
ee/spec/presenters/group_member_presenter_spec.rb
ee/spec/presenters/group_member_presenter_spec.rb
+22
-0
ee/spec/services/dast_site_profiles/update_service_spec.rb
ee/spec/services/dast_site_profiles/update_service_spec.rb
+1
-1
lib/gitlab/graphql/global_id_compatibility.rb
lib/gitlab/graphql/global_id_compatibility.rb
+20
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/lib/utils/datetime_utility_spec.js
spec/frontend/lib/utils/datetime_utility_spec.js
+23
-0
spec/graphql/types/global_id_type_spec.rb
spec/graphql/types/global_id_type_spec.rb
+18
-8
spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb
...ntexts/cache_allowed_users_in_namespace_shared_context.rb
+1
-1
No files found.
app/assets/javascripts/ide/components/file_templates/dropdown.vue
View file @
8f6e28e5
<
script
>
import
$
from
'
jquery
'
;
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
Gl
Icon
,
Gl
LoadingIcon
}
from
'
@gitlab/ui
'
;
import
DropdownButton
from
'
~/vue_shared/components/dropdown/dropdown_button.vue
'
;
export
default
{
components
:
{
DropdownButton
,
GlIcon
,
GlLoadingIcon
,
},
props
:
{
...
...
@@ -85,7 +86,7 @@ export default {
type=
"search"
class=
"dropdown-input-field qa-dropdown-filter-input"
/>
<
i
aria-hidden=
"true"
class=
"fa fa-search dropdown-input-search"
></i
>
<
gl-icon
name=
"search"
class=
"dropdown-input-search"
aria-hidden=
"true"
/
>
</div>
<div
class=
"dropdown-content"
>
<gl-loading-icon
v-if=
"showLoading"
size=
"lg"
/>
...
...
app/assets/javascripts/lib/utils/datetime_utility.js
View file @
8f6e28e5
...
...
@@ -743,3 +743,22 @@ export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
const
endDateInMS
=
endDate
instanceof
Date
?
endDate
.
getTime
()
:
endDate
;
return
endDateInMS
-
startDateInMS
;
};
/**
* A utility which returns a new date at the first day of the month for any given date.
*
* @param {Date} date
*
* @return {Date} the date at the first day of the month
*/
export
const
dateAtFirstDayOfMonth
=
date
=>
new
Date
(
newDate
(
date
).
setDate
(
1
));
/**
* A utility function which checks if two dates match.
*
* @param {Date|Int} date1 Can be either a date object or a unix timestamp.
* @param {Date|Int} date2 Can be either a date object or a unix timestamp.
*
* @return {Boolean} true if the dates match
*/
export
const
datesMatch
=
(
date1
,
date2
)
=>
differenceInMilliseconds
(
date1
,
date2
)
===
0
;
app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
View file @
8f6e28e5
<
script
>
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
~/locale
'
;
export
default
{
components
:
{
GlIcon
,
},
props
:
{
placeholderText
:
{
type
:
String
,
...
...
@@ -41,5 +45,6 @@ export default {
autocomplete=
"off"
/>
<i
class=
"fa fa-search dropdown-input-search"
aria-hidden=
"true"
data-hidden=
"true"
>
</i>
<gl-icon
name=
"search"
class=
"dropdown-input-search"
aria-hidden=
"true"
data-hidden=
"true"
/>
</div>
</
template
>
app/assets/javascripts/vue_shared/components/file_finder/index.vue
View file @
8f6e28e5
...
...
@@ -230,13 +230,12 @@ export default {
@
keydown=
"onKeydown($event)"
@
keyup=
"onKeyup($event)"
/>
<
i
:class=
"
{
hidden: showClearInputButton,
}"
<
gl-icon
name=
"search"
class=
"dropdown-input-search"
:class=
"
{ hidden: showClearInputButton
}"
aria-hidden="true"
class="fa fa-search dropdown-input-search"
>
</i>
/>
<gl-icon
name=
"close"
class=
"dropdown-input-clear"
...
...
app/assets/stylesheets/pages/diff.scss
View file @
8f6e28e5
...
...
@@ -431,10 +431,6 @@
margin-left
:
0
;
border-left
:
0
;
}
.file-actions
.dropdown
{
height
:
28px
;
}
}
table
.code
{
...
...
app/finders/group_members_finder.rb
View file @
8f6e28e5
...
...
@@ -17,9 +17,8 @@ class GroupMembersFinder < UnionFinder
@params
=
params
end
# rubocop: disable CodeReuse/ActiveRecord
def
execute
(
include_relations:
[
:inherited
,
:direct
])
group_members
=
group
.
members
group_members
=
group
_members_list
relations
=
[]
return
group_members
if
include_relations
==
[
:direct
]
...
...
@@ -27,17 +26,13 @@ class GroupMembersFinder < UnionFinder
relations
<<
group_members
if
include_relations
.
include?
(
:direct
)
if
include_relations
.
include?
(
:inherited
)
&&
group
.
parent
parents_members
=
GroupMember
.
non_request
.
non_minimal_access
.
where
(
source_id:
group
.
ancestors
.
select
(
:id
))
.
where
.
not
(
user_id:
group
.
users
.
select
(
:id
))
parents_members
=
relation_group_members
(
group
.
ancestors
)
relations
<<
parents_members
end
if
include_relations
.
include?
(
:descendants
)
descendant_members
=
GroupMember
.
non_request
.
non_minimal_access
.
where
(
source_id:
group
.
descendants
.
select
(
:id
))
.
where
.
not
(
user_id:
group
.
users
.
select
(
:id
))
descendant_members
=
relation_group_members
(
group
.
descendants
)
relations
<<
descendant_members
end
...
...
@@ -47,7 +42,6 @@ class GroupMembersFinder < UnionFinder
members
=
find_union
(
relations
,
GroupMember
)
filter_members
(
members
)
end
# rubocop: enable CodeReuse/ActiveRecord
private
...
...
@@ -67,6 +61,22 @@ class GroupMembersFinder < UnionFinder
def
can_manage_members
Ability
.
allowed?
(
user
,
:admin_group_member
,
group
)
end
def
group_members_list
group
.
members
end
def
relation_group_members
(
relation
)
all_group_members
(
relation
).
non_minimal_access
end
# rubocop: disable CodeReuse/ActiveRecord
def
all_group_members
(
relation
)
GroupMember
.
non_request
.
where
(
source_id:
relation
.
select
(
:id
))
.
where
.
not
(
user_id:
group
.
users
.
select
(
:id
))
end
# rubocop: enable CodeReuse/ActiveRecord
end
GroupMembersFinder
.
prepend_if_ee
(
'EE::GroupMembersFinder'
)
app/graphql/mutations/base_mutation.rb
View file @
8f6e28e5
...
...
@@ -4,6 +4,7 @@ module Mutations
class
BaseMutation
<
GraphQL
::
Schema
::
RelayClassicMutation
prepend
Gitlab
::
Graphql
::
Authorize
::
AuthorizeResource
prepend
Gitlab
::
Graphql
::
CopyFieldDescription
prepend
::
Gitlab
::
Graphql
::
GlobalIDCompatibility
ERROR_MESSAGE
=
'You cannot perform write operations on a read-only instance'
...
...
app/graphql/mutations/ci/base.rb
View file @
8f6e28e5
...
...
@@ -3,13 +3,18 @@
module
Mutations
module
Ci
class
Base
<
BaseMutation
argument
:id
,
::
Types
::
GlobalIDType
[
::
Ci
::
Pipeline
],
PipelineID
=
::
Types
::
GlobalIDType
[
::
Ci
::
Pipeline
]
argument
:id
,
PipelineID
,
required:
true
,
description:
'The id of the pipeline to mutate'
private
def
find_object
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
PipelineID
.
coerce_isolated_input
(
id
)
GlobalID
::
Locator
.
locate
(
id
)
end
end
...
...
app/graphql/mutations/design_management/move.rb
View file @
8f6e28e5
...
...
@@ -29,11 +29,18 @@ module Mutations
private
def
parameters
(
**
args
)
args
.
transform_values
{
|
id
|
GitlabSchema
.
find_by_gid
(
id
)
}.
transform_values
(
&
:sync
).
tap
do
|
hash
|
args
.
transform_values
{
|
id
|
find_design
(
id
)
}.
transform_values
(
&
:sync
).
tap
do
|
hash
|
hash
.
each
{
|
k
,
design
|
not_found
(
args
[
k
])
unless
current_user
.
can?
(
:read_design
,
design
)
}
end
end
def
find_design
(
id
)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
DesignID
.
coerce_isolated_input
(
id
)
GitlabSchema
.
object_from_id
(
id
)
end
def
not_found
(
gid
)
raise
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
,
"Resource not available:
#{
gid
}
"
end
...
...
app/graphql/resolvers/base_resolver.rb
View file @
8f6e28e5
...
...
@@ -4,6 +4,7 @@ module Resolvers
class
BaseResolver
<
GraphQL
::
Schema
::
Resolver
extend
::
Gitlab
::
Utils
::
Override
include
::
Gitlab
::
Utils
::
StrongMemoize
include
::
Gitlab
::
Graphql
::
GlobalIDCompatibility
def
self
.
single
@single
||=
Class
.
new
(
self
)
do
...
...
app/graphql/types/global_id_type.rb
View file @
8f6e28e5
# frozen_string_literal: true
module
GraphQLExtensions
module
ScalarExtensions
# Allow ID to unify with GlobalID Types
def
==
(
other
)
if
name
==
'ID'
&&
other
.
is_a?
(
self
.
class
)
&&
other
.
type_class
.
ancestors
.
include?
(
::
Types
::
GlobalIDType
)
return
true
end
super
end
end
end
::
GraphQL
::
ScalarType
.
prepend
(
GraphQLExtensions
::
ScalarExtensions
)
module
Types
class
GlobalIDType
<
BaseScalar
graphql_name
'GlobalID'
...
...
app/graphql/types/query_type.rb
View file @
8f6e28e5
...
...
@@ -49,8 +49,7 @@ module Types
field
:milestone
,
::
Types
::
MilestoneType
,
null:
true
,
description:
'Find a milestone'
,
resolve:
->
(
_obj
,
args
,
_ctx
)
{
GitlabSchema
.
find_by_gid
(
args
[
:id
])
}
do
description:
'Find a milestone'
do
argument
:id
,
::
Types
::
GlobalIDType
[
Milestone
],
required:
true
,
description:
'Find a milestone by its ID'
...
...
@@ -86,7 +85,17 @@ module Types
end
def
issue
(
id
:)
GitlabSchema
.
object_from_id
(
id
,
expected_type:
::
Issue
)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
::
Issue
].
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
def
milestone
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
Milestone
].
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
end
...
...
app/helpers/groups/group_members_helper.rb
View file @
8f6e28e5
...
...
@@ -10,7 +10,7 @@ module Groups::GroupMembersHelper
end
def
render_invite_member_for_group
(
group
,
default_access_level
)
render
'shared/members/invite_member'
,
submit_url:
group_group_members_path
(
group
),
access_levels:
GroupMember
.
access_level_roles
,
default_access_level:
default_access_level
render
'shared/members/invite_member'
,
submit_url:
group_group_members_path
(
group
),
access_levels:
group
.
access_level_roles
,
default_access_level:
default_access_level
end
def
linked_groups_data_json
(
group_links
)
...
...
app/models/group.rb
View file @
8f6e28e5
...
...
@@ -356,6 +356,7 @@ class Group < Namespace
end
group_hierarchy_members
=
GroupMember
.
active_without_invites_and_requests
.
non_minimal_access
.
where
(
source_id:
source_ids
)
GroupMember
.
from_union
([
group_hierarchy_members
,
...
...
@@ -550,6 +551,14 @@ class Group < Namespace
owners
.
first
||
parent
&
.
default_owner
||
owner
end
def
access_level_roles
GroupMember
.
access_level_roles
end
def
access_level_values
access_level_roles
.
values
end
private
def
update_two_factor_requirement
...
...
app/models/user.rb
View file @
8f6e28e5
...
...
@@ -132,6 +132,8 @@ class User < ApplicationRecord
->
{
where
(
members:
{
access_level:
[
Gitlab
::
Access
::
REPORTER
,
Gitlab
::
Access
::
DEVELOPER
,
Gitlab
::
Access
::
MAINTAINER
,
Gitlab
::
Access
::
OWNER
]
})
},
through: :group_members
,
source: :group
has_many
:minimal_access_group_members
,
->
{
where
(
access_level:
[
Gitlab
::
Access
::
MINIMAL_ACCESS
])
},
source:
'GroupMember'
,
class_name:
'GroupMember'
has_many
:minimal_access_groups
,
through: :minimal_access_group_members
,
source: :group
# Projects
has_many
:groups_projects
,
through: :groups
,
source: :projects
...
...
app/views/admin/groups/show.html.haml
View file @
8f6e28e5
...
...
@@ -113,7 +113,7 @@
%div
=
users_select_tag
(
:user_ids
,
multiple:
true
,
email_user:
true
,
skip_ldap:
@group
.
ldap_synced?
,
scope: :all
)
.gl-mt-3
=
select_tag
:access_level
,
options_for_select
(
GroupMember
.
access_level_roles
),
class:
"project-access-select select2"
=
select_tag
:access_level
,
options_for_select
(
@group
.
access_level_roles
),
class:
"project-access-select select2"
%hr
=
button_tag
_
(
'Add users to group'
),
class:
"btn btn-success"
=
render
'shared/members/requests'
,
membership_source:
@group
,
requesters:
@requesters
,
force_mobile_view:
true
...
...
changelogs/unreleased/220203-gitlab-com-sso-create-no-access-role-fe-changes.yml
0 → 100644
View file @
8f6e28e5
---
title
:
Add No Access Role for top group members
merge_request
:
40942
author
:
type
:
added
changelogs/unreleased/mw-replace-fa-search-icons.yml
0 → 100644
View file @
8f6e28e5
---
title
:
Replace fa-search fontawesome icons with GitLab SVG in Vue components
merge_request
:
43879
author
:
type
:
changed
config/feature_flags/licensed/minimal_access_role.yml
0 → 100644
View file @
8f6e28e5
---
name
:
minimal_access_role
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942
rollout_issue_url
:
group
:
group::access
type
:
licensed
default_enabled
:
true
doc/development/api_graphql_styleguide.md
View file @
8f6e28e5
...
...
@@ -49,6 +49,20 @@ See also:
-
[
Exposing Global IDs
](
#exposing-global-ids
)
.
-
[
Mutation arguments
](
#object-identifier-arguments
)
.
We have a custom scalar type (
`Types::GlobalIDType`
) which should be used as the
type of input and output arguments when the value is a
`GlobalID`
. The benefits
of using this type instead of
`ID`
are:
-
it validates that the value is a
`GlobalID`
-
it parses it into a
`GlobalID`
before passing it to user code
-
it can be parameterized on the type of the object (e.g.
`GlobalIDType[Project]`
) which offers even better validation and security.
Consider using this type for all new arguments and result types. Remember that
it is perfectly possible to parameterize this type with a concern or a
supertype, if you want to accept a wider range of objects (e.g.
`GlobalIDType[Issuable]`
vs
`GlobalIDType[Issue]`
).
## Types
We use a code-first schema, and we declare what type everything is in Ruby.
...
...
ee/app/assets/javascripts/audit_events/components/audit_events_app.vue
View file @
8f6e28e5
...
...
@@ -58,9 +58,9 @@ export default {
<audit-events-export-button
v-if=
"hasExportUrl"
:export-href=
"exportHref"
/>
</div>
</header>
<div
class=
"row-content-block second-block pb-0"
>
<div
class=
"
d-flex justify-content-between audit-controls row
"
>
<div
class=
"
col-lg-auto flex-fill form-group align-items-lg-center pr-lg-8
"
>
<div
class=
"row-content-block second-block
gl-
pb-0"
>
<div
class=
"
gl-display-flex gl-justify-content-space-between audit-controls gl-flex-wrap
"
>
<div
class=
"
gl-mb-5 gl-w-full
"
>
<audit-events-filter
:filter-token-options=
"filterTokenOptions"
:value=
"filterValue"
...
...
@@ -68,9 +68,9 @@ export default {
@
submit=
"searchForAuditEvents"
/>
</div>
<div
class=
"
d-flex col-lg-auto flex-wrap pl-lg-0
"
>
<div
class=
"
gl-display-flex gl-flex-wrap gl-w-full
"
>
<div
class=
"audit-controls
d-flex align-items-lg-center flex-column flex-lg-row col-lg-auto px-0
"
class=
"audit-controls
gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-justify-content-space-between gl-px-0 gl-w-full
"
>
<date-range-field
:start-date=
"startDate"
...
...
ee/app/assets/javascripts/audit_events/components/date_range_buttons.vue
0 → 100644
View file @
8f6e28e5
<
script
>
import
{
GlButtonGroup
,
GlButton
}
from
'
@gitlab/ui
'
;
import
{
n__
,
s__
}
from
'
~/locale
'
;
import
{
datesMatch
,
dateAtFirstDayOfMonth
,
getDateInPast
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
CURRENT_DATE
}
from
'
../constants
'
;
const
DATE_RANGE_OPTIONS
=
[
{
text
:
n__
(
'
Last %d day
'
,
'
Last %d days
'
,
7
),
startDate
:
getDateInPast
(
CURRENT_DATE
,
7
),
endDate
:
CURRENT_DATE
,
},
{
text
:
n__
(
'
Last %d day
'
,
'
Last %d days
'
,
14
),
startDate
:
getDateInPast
(
CURRENT_DATE
,
14
),
endDate
:
CURRENT_DATE
,
},
{
text
:
s__
(
'
AuditLogs|This month
'
),
startDate
:
dateAtFirstDayOfMonth
(
CURRENT_DATE
),
endDate
:
CURRENT_DATE
,
},
];
export
default
{
components
:
{
GlButton
,
GlButtonGroup
,
},
props
:
{
dateRange
:
{
type
:
Object
,
required
:
true
,
},
},
methods
:
{
onDateRangeClicked
({
startDate
,
endDate
})
{
this
.
$emit
(
'
input
'
,
{
startDate
,
endDate
});
},
isCurrentDateRange
({
startDate
,
endDate
})
{
const
{
dateRange
}
=
this
;
return
datesMatch
(
startDate
,
dateRange
.
startDate
)
&&
datesMatch
(
endDate
,
dateRange
.
endDate
);
},
},
DATE_RANGE_OPTIONS
,
};
</
script
>
<
template
>
<gl-button-group>
<gl-button
v-for=
"(dateRangeOption, idx) in $options.DATE_RANGE_OPTIONS"
:key=
"idx"
:selected=
"isCurrentDateRange(dateRangeOption)"
@
click=
"onDateRangeClicked(dateRangeOption)"
>
{{
dateRangeOption
.
text
}}
</gl-button
>
</gl-button-group>
</
template
>
ee/app/assets/javascripts/audit_events/components/date_range_field.vue
View file @
8f6e28e5
<
script
>
import
{
GlDaterangePicker
}
from
'
@gitlab/ui
'
;
import
{
dateAtFirstDayOfMonth
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
CURRENT_DATE
,
MAX_DATE_RANGE
}
from
'
../constants
'
;
import
DateRangeButtons
from
'
./date_range_buttons.vue
'
;
export
default
{
components
:
{
DateRangeButtons
,
GlDaterangePicker
,
},
props
:
{
...
...
@@ -17,21 +21,43 @@ export default {
default
:
null
,
},
},
computed
:
{
defaultStartDate
()
{
return
this
.
startDate
||
dateAtFirstDayOfMonth
(
CURRENT_DATE
);
},
defaultEndDate
()
{
return
this
.
endDate
||
CURRENT_DATE
;
},
defaultDateRange
()
{
return
{
startDate
:
this
.
defaultStartDate
,
endDate
:
this
.
defaultEndDate
};
},
},
methods
:
{
onInput
(
dates
)
{
this
.
$emit
(
'
selected
'
,
dates
);
},
},
CURRENT_DATE
,
MAX_DATE_RANGE
,
};
</
script
>
<
template
>
<gl-daterange-picker
class=
"d-flex flex-wrap flex-sm-nowrap"
:default-start-date=
"startDate"
:default-end-date=
"endDate"
start-picker-class=
"form-group align-items-lg-center mr-0 mr-sm-1 d-flex flex-column flex-lg-row"
end-picker-class=
"form-group align-items-lg-center mr-0 mr-sm-2 d-flex flex-column flex-lg-row"
@
input=
"onInput"
/>
<div
class=
"gl-display-flex gl-align-items-flex-end gl-xs-align-items-baseline gl-xs-flex-direction-column"
>
<div
class=
"gl-pr-5 gl-mb-5"
>
<date-range-buttons
:date-range=
"defaultDateRange"
@
input=
"onInput"
/>
</div>
<gl-daterange-picker
class=
"gl-display-flex gl-pl-0 gl-w-full"
:default-start-date=
"defaultStartDate"
:default-end-date=
"defaultEndDate"
:default-max-date=
"$options.CURRENT_DATE"
:max-date-range=
"$options.MAX_DATE_RANGE"
start-picker-class=
"gl-mb-5 gl-pr-5 gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-flex-fill-1"
end-picker-class=
"gl-mb-5 gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-flex-fill-1"
@
input=
"onInput"
/>
</div>
</
template
>
ee/app/assets/javascripts/audit_events/components/sorting_field.vue
View file @
8f6e28e5
...
...
@@ -47,7 +47,7 @@ export default {
<
template
>
<div>
<gl-dropdown
:text=
"selectedOption.text"
class=
"w-100 flex-column flex-lg-row
form-group
"
>
<gl-dropdown
:text=
"selectedOption.text"
class=
"w-100 flex-column flex-lg-row
gl-mb-5
"
>
<gl-dropdown-section-header>
{{
$options
.
SORTING_TITLE
}}
</gl-dropdown-section-header>
<gl-dropdown-item
v-for=
"option in $options.SORTING_OPTIONS"
...
...
ee/app/assets/javascripts/audit_events/constants.js
View file @
8f6e28e5
...
...
@@ -56,3 +56,7 @@ export const AUDIT_FILTER_CONFIGS = [
];
export
const
AVAILABLE_TOKEN_TYPES
=
AUDIT_FILTER_CONFIGS
.
map
(
token
=>
token
.
type
);
export
const
MAX_DATE_RANGE
=
31
;
export
const
CURRENT_DATE
=
new
Date
();
ee/app/assets/javascripts/boards/components/boards_list_selector/list_filter.vue
View file @
8f6e28e5
...
...
@@ -31,7 +31,7 @@ export default {
class=
"dropdown-input-field"
@
keyup=
"handleInputChange"
/>
<
i
class=
"fa fa-search dropdown-input-search"
aria-hidden=
"true"
data-hidden=
"true"
></i
>
<
gl-icon
name=
"search"
class=
"dropdown-input-search"
aria-hidden=
"true"
data-hidden=
"true"
/
>
<gl-icon
name=
"close"
class=
"dropdown-input-clear"
...
...
ee/app/assets/stylesheets/components/audit_logs/sorting_field.scss
View file @
8f6e28e5
.audit-controls
.gl-dropdown-toggle
{
border-color
:
$gray-100
;
border-radius
:
0
.25rem
;
box-shadow
:
inset
0
0
0
0
.0625rem
$gray-200
;
padding
:
0
.5rem
0
.75rem
;
.audit-controls
{
.gl-dropdown-toggle
{
border-color
:
$gray-100
;
border-radius
:
0
.25rem
;
box-shadow
:
inset
0
0
0
0
.0625rem
$gray-200
;
padding
:
0
.5rem
0
.75rem
;
}
.gl-daterange-picker
>
div
{
@include
media-breakpoint-up
(
lg
)
{
align-items
:
baseline
;
}
}
}
ee/app/controllers/ee/admin/groups_controller.rb
View file @
8f6e28e5
...
...
@@ -4,6 +4,8 @@
module
EE
module
Admin
module
GroupsController
extend
::
Gitlab
::
Utils
::
Override
def
reset_runners_minutes
group
...
...
@@ -25,6 +27,13 @@ module EE
]
end
override
:group_members
def
group_members
return
@group
.
all_group_members
if
@group
.
minimal_access_role_allowed?
@group
.
members
end
def
groups
super
.
with_deletion_schedule
end
...
...
ee/app/finders/ee/group_members_finder.rb
View file @
8f6e28e5
...
...
@@ -2,6 +2,7 @@
module
EE::GroupMembersFinder
extend
ActiveSupport
::
Concern
extend
::
Gitlab
::
Utils
::
Override
prepended
do
attr_reader
:group
...
...
@@ -12,4 +13,18 @@ module EE::GroupMembersFinder
group
.
group_members
.
non_owners
.
joins
(
:user
).
merge
(
User
.
not_managed
(
group:
group
))
end
# rubocop: enable CodeReuse/ActiveRecord
override
:group_members_list
def
group_members_list
return
group
.
all_group_members
if
group
.
minimal_access_role_allowed?
super
end
override
:relation_group_members
def
relation_group_members
(
relation
)
return
all_group_members
(
relation
)
if
group
.
minimal_access_role_allowed?
super
end
end
ee/app/graphql/ee/mutations/boards/issues/issue_move_list.rb
View file @
8f6e28e5
...
...
@@ -8,8 +8,10 @@ module EE
extend
ActiveSupport
::
Concern
extend
::
Gitlab
::
Utils
::
Override
EpicID
=
::
Types
::
GlobalIDType
[
::
Epic
]
prepended
do
argument
:epic_id
,
::
Types
::
GlobalIDType
[
::
Epic
]
,
argument
:epic_id
,
EpicID
,
required:
false
,
description:
'The ID of the parent epic. NULL when removing the association'
end
...
...
@@ -28,10 +30,12 @@ module EE
override
:move_arguments
def
move_arguments
(
args
)
allowed_args
=
super
allowed_args
[
:epic_id
]
=
args
[
:epic_id
]
&
.
model_id
if
args
.
has_key?
(
:epic_id
)
# TODO: remove this line once the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
coerce_global_id_arguments!
(
args
)
epic_arguments
=
args
.
slice
(
:epic_id
).
transform_values
{
|
id
|
id
&
.
model_id
}
allowed_args
super
.
merge!
(
epic_arguments
)
end
end
end
...
...
ee/app/graphql/ee/types/project_type.rb
View file @
8f6e28e5
...
...
@@ -87,7 +87,10 @@ module EE
::
Types
::
DastSiteProfileType
,
null:
true
,
resolve:
->
(
obj
,
args
,
_ctx
)
do
DastSiteProfilesFinder
.
new
(
project_id:
obj
.
id
,
id:
args
[
:id
].
model_id
).
execute
.
first
# TODO: remove this coercion when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
gid
=
::
Types
::
GlobalIDType
[
::
DastSiteProfile
].
coerce_isolated_input
(
args
[
:id
])
DastSiteProfilesFinder
.
new
(
project_id:
obj
.
id
,
id:
gid
.
model_id
).
execute
.
first
end
,
description:
'DAST Site Profile associated with the project'
do
argument
:id
,
::
Types
::
GlobalIDType
[
::
DastSiteProfile
],
required:
true
,
description:
'ID of the site profile'
...
...
ee/app/graphql/ee/types/query_type.rb
View file @
8f6e28e5
...
...
@@ -8,7 +8,6 @@ module EE
prepended
do
field
:iteration
,
::
Types
::
IterationType
,
null:
true
,
resolve:
->
(
_obj
,
args
,
_ctx
)
{
::
GitlabSchema
.
find_by_gid
(
args
[
:id
])
},
description:
'Find an iteration'
do
argument
:id
,
::
Types
::
GlobalIDType
[
::
Iteration
],
required:
true
,
...
...
@@ -24,8 +23,7 @@ module EE
field
:vulnerability
,
::
Types
::
VulnerabilityType
,
null:
true
,
description:
"Find a vulnerability"
,
resolve:
->
(
_obj
,
args
,
_ctx
)
{
::
GitlabSchema
.
find_by_gid
(
args
[
:id
])
}
do
description:
"Find a vulnerability"
do
argument
:id
,
::
Types
::
GlobalIDType
[
::
Vulnerability
],
required:
true
,
description:
'The Global ID of the Vulnerability'
...
...
@@ -54,6 +52,20 @@ module EE
resolver:
::
Resolvers
::
InstanceSecurityDashboardResolver
,
description:
'Fields related to Instance Security Dashboard'
end
def
vulnerability
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
::
Vulnerability
].
coerce_isolated_input
(
id
)
::
GitlabSchema
.
find_by_gid
(
id
)
end
def
iteration
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
Iteration
].
coerce_isolated_input
(
id
)
::
GitlabSchema
.
find_by_gid
(
id
)
end
end
end
end
ee/app/graphql/mutations/clusters/agent_tokens/create.rb
View file @
8f6e28e5
...
...
@@ -8,8 +8,9 @@ module Mutations
authorize
:create_cluster
argument
:cluster_agent_id
,
::
Types
::
GlobalIDType
[
::
Clusters
::
Agent
],
ClusterAgentID
=
::
Types
::
GlobalIDType
[
::
Clusters
::
Agent
]
argument
:cluster_agent_id
,
ClusterAgentID
,
required:
true
,
description:
'Global ID of the cluster agent that will be associated with the new token'
...
...
@@ -42,6 +43,9 @@ module Mutations
private
def
find_object
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
ClusterAgentID
.
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
...
...
ee/app/graphql/mutations/clusters/agent_tokens/delete.rb
View file @
8f6e28e5
...
...
@@ -8,8 +8,9 @@ module Mutations
authorize
:admin_cluster
argument
:id
,
::
Types
::
GlobalIDType
[
::
Clusters
::
AgentToken
],
TokenID
=
::
Types
::
GlobalIDType
[
::
Clusters
::
AgentToken
]
argument
:id
,
TokenID
,
required:
true
,
description:
'Global ID of the cluster agent token that will be deleted'
...
...
@@ -23,6 +24,9 @@ module Mutations
private
def
find_object
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
TokenID
.
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
...
...
ee/app/graphql/mutations/clusters/agents/delete.rb
View file @
8f6e28e5
...
...
@@ -8,8 +8,9 @@ module Mutations
authorize
:admin_cluster
argument
:id
,
::
Types
::
GlobalIDType
[
::
Clusters
::
Agent
],
AgentID
=
::
Types
::
GlobalIDType
[
::
Clusters
::
Agent
]
argument
:id
,
AgentID
,
required:
true
,
description:
'Global id of the cluster agent that will be deleted'
...
...
@@ -27,6 +28,9 @@ module Mutations
private
def
find_object
(
id
:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
AgentID
.
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
...
...
ee/app/graphql/mutations/dast_on_demand_scans/create.rb
View file @
8f6e28e5
...
...
@@ -30,6 +30,10 @@ module Mutations
def
resolve
(
full_path
:,
dast_site_profile_id
:,
**
args
)
project
=
authorized_find_project!
(
full_path:
full_path
)
# TODO: remove explicit coercion once compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
dast_site_profile_id
=
::
Types
::
GlobalIDType
[
::
DastSiteProfile
].
coerce_isolated_input
(
dast_site_profile_id
)
dast_site_profile
=
find_dast_site_profile
(
project:
project
,
dast_site_profile_id:
dast_site_profile_id
)
dast_site
=
dast_site_profile
.
dast_site
dast_scanner_profile
=
find_dast_scanner_profile
(
project:
project
,
dast_scanner_profile_id:
args
[
:dast_scanner_profile_id
])
...
...
@@ -63,6 +67,11 @@ module Mutations
def
find_dast_scanner_profile
(
project
:,
dast_scanner_profile_id
:)
return
unless
dast_scanner_profile_id
# TODO: remove explicit coercion once compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
dast_scanner_profile_id
=
::
Types
::
GlobalIDType
[
::
DastScannerProfile
]
.
coerce_isolated_input
(
dast_scanner_profile_id
)
project
.
dast_scanner_profiles
.
find
(
dast_scanner_profile_id
.
model_id
)
...
...
ee/app/graphql/mutations/dast_scanner_profiles/delete.rb
View file @
8f6e28e5
...
...
@@ -7,17 +7,23 @@ module Mutations
graphql_name
'DastScannerProfileDelete'
ScannerProfileID
=
::
Types
::
GlobalIDType
[
::
DastScannerProfile
]
argument
:full_path
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'Full path for the project the scanner profile belongs to.'
argument
:id
,
::
Types
::
GlobalIDType
[
::
DastScannerProfile
]
,
argument
:id
,
ScannerProfileID
,
required:
true
,
description:
'ID of the scanner profile to be deleted.'
authorize
:create_on_demand_dast_scan
def
resolve
(
full_path
:,
id
:)
# TODO: remove this line once the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
ScannerProfileID
.
coerce_isolated_input
(
id
)
project
=
authorized_find_project!
(
full_path:
full_path
)
service
=
::
DastScannerProfiles
::
DestroyService
.
new
(
project
,
current_user
)
...
...
ee/app/graphql/mutations/dast_scanner_profiles/update.rb
View file @
8f6e28e5
...
...
@@ -34,10 +34,14 @@ module Mutations
authorize
:create_on_demand_dast_scan
def
resolve
(
full_path
:,
**
service_args
)
# TODO: remove this explicit coercion once the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
gid
=
::
Types
::
GlobalIDType
[
::
DastScannerProfile
].
coerce_isolated_input
(
service_args
[
:id
])
project
=
authorized_find!
(
full_path:
full_path
)
service
=
::
DastScannerProfiles
::
UpdateService
.
new
(
project
,
current_user
)
result
=
service
.
execute
({
**
service_args
,
id:
service_args
[
:id
]
.
model_id
})
result
=
service
.
execute
({
**
service_args
,
id:
gid
.
model_id
})
if
result
.
success?
{
id:
result
.
payload
.
to_global_id
,
errors:
[]
}
...
...
ee/app/graphql/mutations/dast_site_profiles/delete.rb
View file @
8f6e28e5
...
...
@@ -19,6 +19,10 @@ module Mutations
def
resolve
(
full_path
:,
id
:)
project
=
authorized_find_project!
(
full_path:
full_path
)
# TODO: remove explicit coercion once compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
::
DastSiteProfile
].
coerce_isolated_input
(
id
)
dast_site_profile
=
find_dast_site_profile
(
project:
project
,
global_id:
id
)
return
{
errors:
dast_site_profile
.
errors
.
full_messages
}
unless
dast_site_profile
.
destroy
...
...
ee/app/graphql/mutations/dast_site_profiles/update.rb
View file @
8f6e28e5
...
...
@@ -29,7 +29,10 @@ module Mutations
authorize
:create_on_demand_dast_scan
def
resolve
(
full_path
:,
**
service_args
)
def
resolve
(
full_path
:,
id
:,
**
service_args
)
# TODO: remove explicit coercion once compatibility layer has been removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
service_args
[
:id
]
=
::
Types
::
GlobalIDType
[
::
DastSiteProfile
].
coerce_isolated_input
(
id
).
model_id
project
=
authorized_find_project!
(
full_path:
full_path
)
service
=
::
DastSiteProfiles
::
UpdateService
.
new
(
project
,
current_user
)
...
...
ee/app/graphql/mutations/vulnerabilities/confirm.rb
View file @
8f6e28e5
...
...
@@ -33,6 +33,9 @@ module Mutations
end
def
find_object
(
id
:)
# TODO: remove this line once the compatibility layer is removed.
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
::
Vulnerability
].
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
...
...
ee/app/graphql/mutations/vulnerabilities/resolve.rb
View file @
8f6e28e5
...
...
@@ -33,6 +33,9 @@ module Mutations
end
def
find_object
(
id
:)
# TODO: remove this line once the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id
=
::
Types
::
GlobalIDType
[
::
Vulnerability
].
coerce_isolated_input
(
id
)
GitlabSchema
.
find_by_gid
(
id
)
end
end
...
...
ee/app/models/ee/group.rb
View file @
8f6e28e5
...
...
@@ -408,6 +408,21 @@ module EE
minimal_access_role_allowed?
?
::
Gitlab
::
Access
::
MINIMAL_ACCESS
:
::
Gitlab
::
Access
::
GUEST
end
override
:access_level_roles
def
access_level_roles
levels
=
::
GroupMember
.
access_level_roles
return
levels
unless
minimal_access_role_allowed?
levels
.
merge
(
::
Gitlab
::
Access
::
MINIMAL_ACCESS_HASH
)
end
override
:users_count
def
users_count
return
all_group_members
.
count
unless
minimal_access_role_allowed?
members
.
count
end
private
def
custom_project_templates_group_allowed
...
...
ee/app/models/ee/group_member.rb
View file @
8f6e28e5
...
...
@@ -3,9 +3,9 @@
module
EE
module
GroupMember
extend
ActiveSupport
::
Concern
extend
::
Gitlab
::
Utils
::
Override
prepended
do
extend
::
Gitlab
::
Utils
::
Override
include
UsageStatistics
validate
:sso_enforcement
,
if: :group
...
...
@@ -80,6 +80,14 @@ module EE
private
override
:access_level_inclusion
def
access_level_inclusion
levels
=
source
.
access_level_values
return
if
access_level
.
in?
(
levels
)
errors
.
add
(
:access_level
,
"is not included in the list"
)
end
def
email_does_not_match_any_allowed_domains
(
email
)
_
(
"email '%{email}' does not match the allowed domains of %{email_domains}"
%
{
email:
email
,
email_domains:
::
Gitlab
::
Utils
.
to_exclusive_sentence
(
group_allowed_email_domains
.
map
(
&
:domain
))
})
...
...
ee/app/models/ee/user.rb
View file @
8f6e28e5
...
...
@@ -44,6 +44,9 @@ module EE
has_many
:approvals
,
dependent: :destroy
# rubocop: disable Cop/ActiveRecordDependent
has_many
:approvers
,
dependent: :destroy
# rubocop: disable Cop/ActiveRecordDependent
has_many
:minimal_access_group_members
,
->
{
where
(
access_level:
[
::
Gitlab
::
Access
::
MINIMAL_ACCESS
])
},
source:
'GroupMember'
,
class_name:
'GroupMember'
has_many
:minimal_access_groups
,
through: :minimal_access_group_members
,
source: :group
has_many
:users_ops_dashboard_projects
has_many
:ops_dashboard_projects
,
through: :users_ops_dashboard_projects
,
source: :project
has_many
:users_security_dashboard_projects
...
...
@@ -353,6 +356,18 @@ module EE
owns_paid_namespace?
(
plans:
[
::
Plan
::
BRONZE
,
::
Plan
::
SILVER
])
end
# Returns the groups a user has access to, either through a membership or a project authorization
override
:authorized_groups
def
authorized_groups
::
Group
.
unscoped
do
::
Group
.
from_union
([
groups
,
available_minimal_access_groups
,
authorized_projects
.
joins
(
:namespace
).
select
(
'namespaces.*'
)
])
end
end
protected
override
:password_required?
...
...
@@ -383,5 +398,12 @@ module EE
highest_role
>
::
Gitlab
::
Access
::
GUEST
end
def
available_minimal_access_groups
return
::
Group
.
none
unless
License
.
feature_available?
(
:minimal_access_role
)
return
minimal_access_groups
unless
::
Gitlab
::
CurrentSettings
.
should_check_namespace_plan?
minimal_access_groups
.
with_feature_available_in_plan
(
:minimal_access_role
)
end
end
end
ee/app/models/saml_provider.rb
View file @
8f6e28e5
...
...
@@ -9,7 +9,8 @@ class SamlProvider < ApplicationRecord
validates
:group
,
presence:
true
,
top_level_group:
true
validates
:sso_url
,
presence:
true
,
addressable_url:
{
schemes:
%w(https)
,
ascii_only:
true
}
validates
:certificate_fingerprint
,
presence:
true
,
certificate_fingerprint:
true
validates
:default_membership_role
,
presence:
true
,
inclusion:
{
in:
Gitlab
::
Access
.
values
}
validates
:default_membership_role
,
presence:
true
validate
:access_level_inclusion
after_initialize
:set_defaults
,
if: :new_record?
...
...
@@ -82,6 +83,15 @@ class SamlProvider < ApplicationRecord
private
def
access_level_inclusion
return
errors
.
add
(
:default_membership_role
,
"is dependent on a group"
)
unless
group
levels
=
group
.
access_level_values
return
if
default_membership_role
.
in?
(
levels
)
errors
.
add
(
:default_membership_role
,
"is not included in the list"
)
end
def
set_defaults
self
.
enabled
=
true
end
...
...
ee/app/presenters/ee/group_member_presenter.rb
View file @
8f6e28e5
...
...
@@ -2,6 +2,8 @@
module
EE
module
GroupMemberPresenter
extend
::
Gitlab
::
Utils
::
Override
def
group_sso?
member
.
user
.
group_sso?
(
source
)
end
...
...
@@ -10,6 +12,11 @@ module EE
member
.
user
.
group_managed_account?
end
override
:access_level_roles
def
access_level_roles
member
.
source
.
access_level_roles
end
private
def
override_member_permission
...
...
ee/app/services/dast_site_profiles/update_service.rb
View file @
8f6e28e5
...
...
@@ -30,7 +30,7 @@ module DastSiteProfiles
# rubocop: disable CodeReuse/ActiveRecord
def
find_dast_site_profile!
(
id
)
DastSiteProfilesFinder
.
new
(
project_id:
project
.
id
,
id:
id
.
model_id
).
execute
.
first!
DastSiteProfilesFinder
.
new
(
project_id:
project
.
id
,
id:
id
).
execute
.
first!
end
# rubocop: enable CodeReuse/ActiveRecord
end
...
...
ee/app/services/fetch_subscription_plans_service.rb
View file @
8f6e28e5
...
...
@@ -39,6 +39,10 @@ class FetchSubscriptionPlansService
end
def
cache_key
"subscription-plans-
#{
@plan
}
"
if
Feature
.
enabled?
(
:subscription_plan_cache_key
)
"subscription-plan-
#{
@plan
}
"
else
"subscription-plans-
#{
@plan
}
"
end
end
end
ee/app/views/groups/saml_providers/_form.html.haml
View file @
8f6e28e5
...
...
@@ -50,7 +50,7 @@
.well-segment.borderless.gl-mb-3.col-12.col-lg-9.gl-p-0
=
f
.
label
:default_membership_role
,
class:
'label-bold'
do
=
s_
(
'GroupSAML|Default membership role'
)
=
f
.
select
:default_membership_role
,
options_for_select
(
::
Gitlab
::
Access
.
option
s
,
saml_provider
.
default_membership_role
),
{},
class:
'form-control'
,
data:
{
qa_selector:
'default_membership_role_dropdown'
}
=
f
.
select
:default_membership_role
,
options_for_select
(
group
.
access_level_role
s
,
saml_provider
.
default_membership_role
),
{},
class:
'form-control'
,
data:
{
qa_selector:
'default_membership_role_dropdown'
}
.form-text.text-muted
=
s_
(
'GroupSAML|This will be set as the access level of users added to the group.'
)
...
...
ee/changelogs/unreleased/223260-improve-and-limit-date-filters.yml
0 → 100644
View file @
8f6e28e5
---
title
:
Add quick select date options to audit events filter
merge_request
:
42711
author
:
type
:
added
ee/config/feature_flags/development/subscription_plan_cache_key.yml
0 → 100644
View file @
8f6e28e5
---
name
:
subscription_plan_cache_key
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43973
rollout_issue_url
:
type
:
development
group
:
group::fulfillment
default_enabled
:
false
ee/lib/ee/gitlab/access.rb
View file @
8f6e28e5
...
...
@@ -10,16 +10,26 @@ module EE
module
Access
extend
ActiveSupport
::
Concern
ADMIN
=
60
MINIMAL_ACCESS_HASH
=
{
"Minimal Access"
=>
::
Gitlab
::
Access
::
MINIMAL_ACCESS
}.
freeze
class_methods
do
extend
::
Gitlab
::
Utils
::
Override
def
vulnerability_access_levels
@vulnerability_access_levels
||=
options_with_owner
.
except
(
'Guest'
)
end
def
options_with_minimal_access
options_with_owner
.
merge
(
"Minimal Access"
=>
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)
options_with_owner
.
merge
(
MINIMAL_ACCESS_HASH
)
end
def
values_with_minimal_access
options_with_minimal_access
.
values
end
override
:human_access
def
human_access
(
access
)
options_with_minimal_access
.
key
(
access
)
end
end
end
...
...
ee/spec/finders/ee/group_members_finder_spec.rb
View file @
8f6e28e5
...
...
@@ -19,4 +19,35 @@ RSpec.describe GroupMembersFinder do
expect
(
finder
.
not_managed
).
to
eq
([
group_member_membership
])
end
end
describe
'#execute'
do
let_it_be
(
:group_minimal_access_membership
)
do
create
(
:group_member
,
:minimal_access
,
source:
group
,
user:
create
(
:user
))
end
context
'when group does not allow minimal access members'
do
before
do
stub_licensed_features
(
minimal_access_role:
false
)
end
it
'returns only members with full access'
do
result
=
finder
.
execute
(
include_relations:
[
:direct
,
:descendants
])
expect
(
result
.
to_a
).
to
match_array
([
group_owner_membership
,
group_member_membership
,
dedicated_member_account_membership
])
end
end
context
'when group allows minimal access members'
do
before
do
group
.
clear_memoization
(
:feature_available
)
stub_licensed_features
(
minimal_access_role:
true
)
end
it
'also returns members with minimal access'
do
result
=
finder
.
execute
(
include_relations:
[
:direct
,
:descendants
])
expect
(
result
.
to_a
).
to
match_array
([
group_owner_membership
,
group_member_membership
,
dedicated_member_account_membership
,
group_minimal_access_membership
])
end
end
end
end
ee/spec/frontend/audit_events/components/__snapshots__/audit_events_app_spec.js.snap
View file @
8f6e28e5
...
...
@@ -13,13 +13,13 @@ exports[`AuditEventsApp when initialized matches the snapshot 1`] = `
</header>
<div
class="row-content-block second-block pb-0"
class="row-content-block second-block
gl-
pb-0"
>
<div
class="
d-flex justify-content-between audit-controls row
"
class="
gl-display-flex gl-justify-content-space-between audit-controls gl-flex-wrap
"
>
<div
class="
col-lg-auto flex-fill form-group align-items-lg-center pr-lg-8
"
class="
gl-mb-5 gl-w-full
"
>
<div
class="input-group bg-white flex-grow-1"
...
...
@@ -37,10 +37,10 @@ exports[`AuditEventsApp when initialized matches the snapshot 1`] = `
</div>
<div
class="
d-flex col-lg-auto flex-wrap pl-lg-0
"
class="
gl-display-flex gl-flex-wrap gl-w-full
"
>
<div
class="audit-controls
d-flex align-items-lg-center flex-column flex-lg-row col-lg-auto px-0
"
class="audit-controls
gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-justify-content-space-between gl-px-0 gl-w-full
"
>
<date-range-field-stub
enddate="Sun Feb 02 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"
...
...
ee/spec/frontend/audit_events/components/date_range_buttons_spec.js
0 → 100644
View file @
8f6e28e5
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlButtonGroup
,
GlButton
}
from
'
@gitlab/ui
'
;
import
DateRangeButtons
from
'
ee/audit_events/components/date_range_buttons.vue
'
;
import
{
CURRENT_DATE
}
from
'
ee/audit_events/constants
'
;
import
{
getDateInPast
}
from
'
~/lib/utils/datetime_utility
'
;
describe
(
'
DateRangeButtons component
'
,
()
=>
{
let
wrapper
;
const
createComponent
=
(
props
=
{})
=>
{
wrapper
=
shallowMount
(
DateRangeButtons
,
{
propsData
:
{
...
props
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
it
(
'
shows the selected the option that matches the provided dateRange property
'
,
()
=>
{
createComponent
({
dateRange
:
{
startDate
:
getDateInPast
(
CURRENT_DATE
,
7
),
endDate
:
CURRENT_DATE
},
});
expect
(
wrapper
.
find
(
GlButtonGroup
)
.
find
(
'
[selected="true"]
'
)
.
text
(),
).
toBe
(
'
Last 7 days
'
);
});
it
(
'
shows no date range as selected when the dateRange property does not match any option
'
,
()
=>
{
createComponent
({
dateRange
:
{
startDate
:
getDateInPast
(
CURRENT_DATE
,
5
),
endDate
:
getDateInPast
(
CURRENT_DATE
,
2
),
},
});
expect
(
wrapper
.
find
(
GlButtonGroup
)
.
find
(
'
[selected="true"]
'
)
.
exists
(),
).
toBe
(
false
);
});
it
(
'
emits an "input" event with the dateRange when a new date range is selected
'
,
async
()
=>
{
createComponent
({
dateRange
:
{
startDate
:
getDateInPast
(
CURRENT_DATE
,
1
),
endDate
:
CURRENT_DATE
},
});
wrapper
.
find
(
GlButtonGroup
)
.
find
(
GlButton
)
.
vm
.
$emit
(
'
click
'
);
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
emitted
().
input
[
0
]).
toEqual
([
{
startDate
:
getDateInPast
(
CURRENT_DATE
,
7
),
endDate
:
CURRENT_DATE
,
},
]);
});
});
ee/spec/frontend/audit_events/components/date_range_field_spec.js
View file @
8f6e28e5
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlDaterangePicker
}
from
'
@gitlab/ui
'
;
import
DateRangeButtons
from
'
ee/audit_events/components/date_range_buttons.vue
'
;
import
DateRangeField
from
'
ee/audit_events/components/date_range_field.vue
'
;
import
{
parsePikadayDate
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
CURRENT_DATE
,
MAX_DATE_RANGE
}
from
'
ee/audit_events/constants
'
;
import
{
dateAtFirstDayOfMonth
,
parsePikadayDate
}
from
'
~/lib/utils/datetime_utility
'
;
describe
(
'
DateRangeField component
'
,
()
=>
{
let
wrapper
;
...
...
@@ -10,6 +12,9 @@ describe('DateRangeField component', () => {
const
startDate
=
parsePikadayDate
(
'
2020-03-13
'
);
const
endDate
=
parsePikadayDate
(
'
2020-03-14
'
);
const
findDatePicker
=
()
=>
wrapper
.
find
(
GlDaterangePicker
);
const
findDateRangeButtons
=
()
=>
wrapper
.
find
(
DateRangeButtons
);
const
createComponent
=
(
props
=
{})
=>
{
wrapper
=
shallowMount
(
DateRangeField
,
{
propsData
:
{
...
props
},
...
...
@@ -21,39 +26,74 @@ describe('DateRangeField component', () => {
wrapper
=
null
;
});
it
(
'
passes the startDate to the date picker as defaultStartDate
'
,
()
=>
{
createComponent
({
startDate
});
describe
(
'
default behaviour
'
,
()
=>
{
it
(
'
sets the max date range on the date picker
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
GlDaterangePicker
).
props
()).
toMatchObject
({
defaultStartDate
:
startDate
,
defaultEndDate
:
null
,
expect
(
findDatePicker
().
props
(
'
maxDateRange
'
)).
toBe
(
MAX_DATE_RANGE
);
});
it
(
"
sets the max selectable date to today's date on the date picker
"
,
()
=>
{
createComponent
();
expect
(
findDatePicker
()
.
props
(
'
defaultMaxDate
'
)
.
toDateString
(),
).
toBe
(
CURRENT_DATE
.
toDateString
());
});
});
it
(
'
passes the endDate to the date picker as defaultEndDate
'
,
()
=>
{
createComponent
({
endDate
}
);
it
(
'
sets the default start date to the start of the month
'
,
()
=>
{
createComponent
(
);
expect
(
wrapper
.
find
(
GlDaterangePicker
).
props
()).
toMatchObject
({
defaultStartDate
:
null
,
defaultEndDate
:
endDate
,
expect
(
findDatePicker
()
.
props
(
'
defaultStartDate
'
)
.
toDateString
(),
).
toBe
(
dateAtFirstDayOfMonth
(
CURRENT_DATE
).
toDateString
());
});
it
(
"
sets the default end date to today's date
"
,
()
=>
{
createComponent
();
expect
(
findDatePicker
()
.
props
(
'
defaultEndDate
'
)
.
toDateString
(),
).
toBe
(
CURRENT_DATE
.
toDateString
());
});
it
(
'
passes both startDate and endDate to the date picker as default dates
'
,
()
=>
{
createComponent
({
startDate
,
endDate
});
expect
(
findDatePicker
().
props
()).
toMatchObject
({
defaultStartDate
:
startDate
,
defaultEndDate
:
endDate
,
});
});
});
it
(
'
passes both startDate and endDate to the date picker as default dates
'
,
()
=>
{
createComponent
({
startDate
,
endDate
});
describe
(
'
when a new date range is picked
'
,
()
=>
{
it
(
'
emits the "selected" event with the picked startDate and endDate
'
,
async
()
=>
{
createComponent
();
findDatePicker
().
vm
.
$emit
(
'
input
'
,
{
startDate
,
endDate
});
expect
(
wrapper
.
find
(
GlDaterangePicker
).
props
()).
toMatchObject
({
defaultStartDate
:
startDate
,
defaultEndDate
:
endDate
,
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
emitted
().
selected
[
0
]).
toEqual
([
{
startDate
,
endDate
,
},
]);
});
});
it
(
'
should emit the "selected" event with startDate and endDate on input change
'
,
()
=>
{
createComponent
();
wrapper
.
find
(
GlDaterangePicker
).
vm
.
$emit
(
'
input
'
,
{
startDate
,
endDate
});
describe
(
'
when a date range button is pressed
'
,
()
=>
{
it
(
'
emits the "selected" event with the picked startDate and endDate
'
,
async
()
=>
{
createComponent
();
findDateRangeButtons
().
vm
.
$emit
(
'
input
'
,
{
startDate
,
endDate
});
return
wrapper
.
vm
.
$nextTick
(()
=>
{
expect
(
wrapper
.
emitted
().
selected
).
toBeTruthy
();
await
wrapper
.
vm
.
$nextTick
();
expect
(
wrapper
.
emitted
().
selected
[
0
]).
toEqual
([
{
startDate
,
...
...
ee/spec/frontend/boards/components/board_list_selector/list_filter_spec.js
View file @
8f6e28e5
...
...
@@ -74,7 +74,7 @@ describe('ListFilter', () => {
});
it
(
'
renders search input icons
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
i.fa.fa-search
.dropdown-input-search
'
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
.dropdown-input-search
'
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
.dropdown-input-clear
'
).
exists
()).
toBe
(
true
);
});
});
...
...
ee/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
View file @
8f6e28e5
...
...
@@ -52,7 +52,7 @@ RSpec.describe Mutations::Clusters::AgentTokens::Create do
subject
{
mutation
.
resolve
(
cluster_agent_id:
cluster_agent
.
id
)
}
it
'generates an error message when id invalid'
,
:aggregate_failures
do
expect
{
subject
}.
to
raise_error
(
NoMethod
Error
)
expect
{
subject
}.
to
raise_error
(
::
GraphQL
::
Coercion
Error
)
end
end
end
...
...
ee/spec/graphql/mutations/clusters/agent_tokens/delete_spec.rb
View file @
8f6e28e5
...
...
@@ -44,7 +44,7 @@ RSpec.describe Mutations::Clusters::AgentTokens::Delete do
let
(
:global_id
)
{
token
.
id
}
it
'raises an error if the cluster agent id is invalid'
,
:aggregate_failures
do
expect
{
subject
}.
to
raise_error
(
NoMethod
Error
)
expect
{
subject
}.
to
raise_error
(
::
GraphQL
::
Coercion
Error
)
expect
{
token
.
reload
}.
not_to
raise_error
end
end
...
...
ee/spec/graphql/mutations/clusters/agents/delete_spec.rb
View file @
8f6e28e5
...
...
@@ -24,7 +24,7 @@ RSpec.describe Mutations::Clusters::Agents::Delete do
context
'without user permissions'
do
it
'fails to delete the cluster agent'
,
:aggregate_failures
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
expect
{
cluster_agent
.
reload
}.
not_to
raise_error
(
ActiveRecord
::
RecordNotFound
)
expect
{
cluster_agent
.
reload
}.
not_to
raise_error
end
end
...
...
@@ -43,8 +43,8 @@ RSpec.describe Mutations::Clusters::Agents::Delete do
subject
{
mutation
.
resolve
(
id:
cluster_agent
.
id
)
}
it
'raises an error if the cluster agent id is invalid'
,
:aggregate_failures
do
expect
{
subject
}.
to
raise_error
(
NoMethod
Error
)
expect
{
cluster_agent
.
reload
}.
not_to
raise_error
(
ActiveRecord
::
RecordNotFound
)
expect
{
subject
}.
to
raise_error
(
::
GraphQL
::
Coercion
Error
)
expect
{
cluster_agent
.
reload
}.
not_to
raise_error
end
end
end
...
...
ee/spec/models/group_member_spec.rb
View file @
8f6e28e5
...
...
@@ -107,6 +107,50 @@ RSpec.describe GroupMember do
end
end
end
describe
'access level inclusion'
do
let
(
:group
)
{
create
(
:group
)
}
context
'when minimal access user feature switched on'
do
before
do
stub_licensed_features
(
minimal_access_role:
true
)
end
it
'users can have access levels from minimal access to owner'
do
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
NO_ACCESS
)).
to
be_invalid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
GUEST
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
REPORTER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
DEVELOPER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
MAINTAINER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
OWNER
)).
to
be_valid
end
context
'when group is a subgroup'
do
let
(
:subgroup
)
{
create
(
:group
,
parent:
group
)
}
it
'users cannot have minimal access level'
do
expect
(
build
(
:group_member
,
group:
subgroup
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)).
to
be_invalid
end
end
end
context
'when minimal access user feature switched off'
do
before
do
stub_licensed_features
(
minimal_access_role:
false
)
end
it
'users can have access levels from guest to owner'
do
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
NO_ACCESS
)).
to
be_invalid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)).
to
be_invalid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
GUEST
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
REPORTER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
DEVELOPER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
MAINTAINER
)).
to
be_valid
expect
(
build
(
:group_member
,
group:
group
,
user:
create
(
:user
),
access_level:
::
Gitlab
::
Access
::
OWNER
)).
to
be_valid
end
end
end
end
describe
'scopes'
do
...
...
ee/spec/models/group_spec.rb
View file @
8f6e28e5
...
...
@@ -705,7 +705,7 @@ RSpec.describe Group do
context
'with `minimal_access_role` not licensed'
do
before
do
stub_licensed_features
(
minimal_access_role:
false
)
create
(
:group_member
,
:minimal_access
,
user:
user
,
group
:
group
)
create
(
:group_member
,
:minimal_access
,
user:
user
,
source
:
group
)
end
it
{
is_expected
.
to
be_falsey
}
...
...
ee/spec/models/saml_provider_spec.rb
View file @
8f6e28e5
...
...
@@ -62,6 +62,42 @@ RSpec.describe SamlProvider do
expect
(
subject
).
to
allow_value
(
group
).
for
(
:group
)
expect
(
subject
).
not_to
allow_value
(
nested_group
).
for
(
:group
)
end
describe
'access level inclusion'
do
let
(
:group
)
{
create
(
:group
)
}
context
'when minimal access user feature is switched on'
do
before
do
stub_licensed_features
(
minimal_access_role:
true
)
end
it
'default membership role can have access levels from minimal access to owner'
do
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
NO_ACCESS
)).
to
be_invalid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
GUEST
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
REPORTER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
DEVELOPER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
MAINTAINER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
OWNER
)).
to
be_valid
end
end
context
'when minimal access user feature switched off'
do
before
do
stub_licensed_features
(
minimal_access_role:
false
)
end
it
'default membership role can have access levels from guest to owner'
do
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
NO_ACCESS
)).
to
be_invalid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
MINIMAL_ACCESS
)).
to
be_invalid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
GUEST
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
REPORTER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
DEVELOPER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
MAINTAINER
)).
to
be_valid
expect
(
build
(
:saml_provider
,
group:
group
,
default_membership_role:
::
Gitlab
::
Access
::
OWNER
)).
to
be_valid
end
end
end
end
describe
'Default values'
do
...
...
ee/spec/models/user_spec.rb
View file @
8f6e28e5
...
...
@@ -1147,6 +1147,56 @@ RSpec.describe User do
end
end
describe
'#authorized_groups'
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:private_group
)
{
create
(
:group
)
}
let_it_be
(
:child_group
)
{
create
(
:group
,
parent:
private_group
)
}
let_it_be
(
:minimal_access_group
)
{
create
(
:group
)
}
let_it_be
(
:project_group
)
{
create
(
:group
)
}
let_it_be
(
:project
)
{
create
(
:project
,
group:
project_group
)
}
before
do
private_group
.
add_user
(
user
,
Gitlab
::
Access
::
MAINTAINER
)
project
.
add_maintainer
(
user
)
create
(
:group_member
,
:minimal_access
,
user:
user
,
source:
minimal_access_group
)
end
subject
{
user
.
authorized_groups
}
context
'with minimal access role feature unavailable'
do
it
{
is_expected
.
to
contain_exactly
private_group
,
project_group
}
end
context
'with minimal access feature available'
do
before
do
stub_licensed_features
(
minimal_access_role:
true
)
end
context
'feature turned on for all groups'
do
before
do
allow
(
Gitlab
::
CurrentSettings
)
.
to
receive
(
:should_check_namespace_plan?
)
.
and_return
(
false
)
end
it
{
is_expected
.
to
contain_exactly
private_group
,
project_group
,
minimal_access_group
}
end
context
'feature available for specific groups only'
do
before
do
allow
(
Gitlab
::
CurrentSettings
)
.
to
receive
(
:should_check_namespace_plan?
)
.
and_return
(
true
)
create
(
:gitlab_subscription
,
:gold
,
namespace:
minimal_access_group
)
create
(
:group_member
,
:minimal_access
,
user:
user
,
source:
create
(
:group
))
end
it
{
is_expected
.
to
contain_exactly
private_group
,
project_group
,
minimal_access_group
}
end
end
end
describe
'#active_for_authentication?'
do
subject
{
user
.
active_for_authentication?
}
...
...
ee/spec/presenters/group_member_presenter_spec.rb
View file @
8f6e28e5
...
...
@@ -60,4 +60,26 @@ RSpec.describe GroupMemberPresenter do
it
{
expect
(
presenter
.
can_update?
).
to
eq
(
false
)
}
end
end
describe
'#valid_level_roles?'
do
context
'with minimal access role feature switched on'
do
before
do
allow
(
group_member
).
to
receive
(
:highest_group_member
)
allow
(
group_member
).
to
receive_message_chain
(
:class
,
:access_level_roles
).
and_return
(
::
Gitlab
::
Access
.
options_with_owner
)
expect
(
group
).
to
receive
(
:access_level_roles
).
and_return
(
::
Gitlab
::
Access
.
options_with_minimal_access
)
end
it
{
expect
(
presenter
.
valid_level_roles
).
to
eq
(
::
Gitlab
::
Access
.
options_with_minimal_access
)
}
end
context
'with minimal access role feature switched off'
do
it_behaves_like
'#valid_level_roles'
,
:group
do
let
(
:expected_roles
)
{
{
'Developer'
=>
30
,
'Maintainer'
=>
40
,
'Owner'
=>
50
,
'Reporter'
=>
20
}
}
before
do
entity
.
parent
=
group
end
end
end
end
end
ee/spec/services/dast_site_profiles/update_service_spec.rb
View file @
8f6e28e5
...
...
@@ -17,7 +17,7 @@ RSpec.describe DastSiteProfiles::UpdateService do
describe
'#execute'
do
subject
do
described_class
.
new
(
project
,
user
).
execute
(
id:
dast_site_profile
.
to_global_
id
,
id:
dast_site_profile
.
id
,
profile_name:
new_profile_name
,
target_url:
new_target_url
)
...
...
lib/gitlab/graphql/global_id_compatibility.rb
0 → 100644
View file @
8f6e28e5
# frozen_string_literal: true
module
Gitlab
module
Graphql
module
GlobalIDCompatibility
# TODO: remove this module once the compatibility layer is no longer needed.
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
def
coerce_global_id_arguments!
(
args
)
global_id_arguments
=
self
.
class
.
arguments
.
values
.
select
do
|
arg
|
arg
.
type
.
is_a?
(
Class
)
&&
arg
.
type
<=
::
Types
::
GlobalIDType
end
global_id_arguments
.
each
do
|
arg
|
k
=
arg
.
keyword
args
[
k
]
&&=
arg
.
type
.
coerce_isolated_input
(
args
[
k
])
end
end
end
end
end
locale/gitlab.pot
View file @
8f6e28e5
...
...
@@ -3669,6 +3669,9 @@ msgstr ""
msgid "AuditLogs|Target"
msgstr ""
msgid "AuditLogs|This month"
msgstr ""
msgid "AuditLogs|User Events"
msgstr ""
...
...
spec/frontend/lib/utils/datetime_utility_spec.js
View file @
8f6e28e5
...
...
@@ -667,3 +667,26 @@ describe('differenceInMilliseconds', () => {
expect
(
datetimeUtility
.
differenceInMilliseconds
(
startDate
,
endDate
)).
toBe
(
expected
);
});
});
describe
(
'
dateAtFirstDayOfMonth
'
,
()
=>
{
const
date
=
new
Date
(
'
2019-07-16T12:00:00.000Z
'
);
it
(
'
returns the date at the first day of the month
'
,
()
=>
{
const
startDate
=
datetimeUtility
.
dateAtFirstDayOfMonth
(
date
);
const
expectedStartDate
=
new
Date
(
'
2019-07-01T12:00:00.000Z
'
);
expect
(
startDate
).
toStrictEqual
(
expectedStartDate
);
});
});
describe
(
'
datesMatch
'
,
()
=>
{
const
date
=
new
Date
(
'
2019-07-17T00:00:00.000Z
'
);
it
.
each
`
date1 | date2 | expected
${
date
}
|
${
new
Date
(
'
2019-07-17T00:00:00.000Z
'
)}
|
${
true
}
${
date
}
|
${
new
Date
(
'
2019-07-17T12:00:00.000Z
'
)}
|
${
false
}
`
(
'
returns $expected for $date1 matches $date2
'
,
({
date1
,
date2
,
expected
})
=>
{
expect
(
datetimeUtility
.
datesMatch
(
date1
,
date2
)).
toBe
(
expected
);
});
});
spec/graphql/types/global_id_type_spec.rb
View file @
8f6e28e5
...
...
@@ -99,8 +99,6 @@ RSpec.describe Types::GlobalIDType do
end
describe
'compatibility'
do
# Simplified schema to test compatibility
def
query
(
doc
,
vars
)
GraphQL
::
Query
.
new
(
schema
,
document:
doc
,
context:
{},
variables:
vars
)
end
...
...
@@ -112,6 +110,7 @@ RSpec.describe Types::GlobalIDType do
all_types
=
[
::
GraphQL
::
ID_TYPE
,
::
Types
::
GlobalIDType
,
::
Types
::
GlobalIDType
[
::
Project
]]
shared_examples
'a working query'
do
# Simplified schema to test compatibility
let!
(
:schema
)
do
# capture values so they can be closed over
arg_type
=
argument_type
...
...
@@ -135,10 +134,21 @@ RSpec.describe Types::GlobalIDType do
argument
:id
,
arg_type
,
required:
true
end
# This is needed so that all types are always registered as input types
field
:echo
,
String
,
null:
true
do
argument
:id
,
::
GraphQL
::
ID_TYPE
,
required:
false
argument
:gid
,
::
Types
::
GlobalIDType
,
required:
false
argument
:pid
,
::
Types
::
GlobalIDType
[
::
Project
],
required:
false
end
def
project_by_id
(
id
:)
gid
=
::
Types
::
GlobalIDType
[
::
Project
].
coerce_isolated_input
(
id
)
gid
.
model_class
.
find
(
gid
.
model_id
)
end
def
echo
(
id:
nil
,
gid:
nil
,
pid:
nil
)
"id:
#{
id
}
, gid:
#{
gid
}
, pid:
#{
pid
}
"
end
end
)
end
end
...
...
@@ -152,7 +162,7 @@ RSpec.describe Types::GlobalIDType do
end
end
context
'when the
argument is declared as ID
'
do
context
'when the
client declares the argument as ID the actual argument can be any type
'
do
let
(
:document
)
do
<<-
GRAPHQL
query($projectId: ID!){
...
...
@@ -163,16 +173,16 @@ RSpec.describe Types::GlobalIDType do
GRAPHQL
end
let
(
:argument_type
)
{
::
GraphQL
::
ID_TYPE
}
where
(
:result_type
)
{
all_types
}
where
(
:result_type
,
:argument_type
)
do
all_types
.
flat_map
{
|
arg_type
|
all_types
.
zip
([
arg_type
].
cycle
)
}
end
with_them
do
it_behaves_like
'a working query'
end
end
context
'when the
argument is declared
as GlobalID'
do
context
'when the
client passes the argument
as GlobalID'
do
let
(
:document
)
do
<<-
GRAPHQL
query($projectId: GlobalID!) {
...
...
@@ -192,7 +202,7 @@ RSpec.describe Types::GlobalIDType do
end
end
context
'when the
argument is declared
as ProjectID'
do
context
'when the
client passes the argument
as ProjectID'
do
let
(
:document
)
do
<<-
GRAPHQL
query($projectId: ProjectID!) {
...
...
spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb
View file @
8f6e28e5
...
...
@@ -25,7 +25,7 @@ RSpec.shared_examples 'allowed user IDs are cached' do
expect
(
described_class
.
l1_cache_backend
).
to
receive
(
:fetch
).
and_call_original
expect
(
described_class
.
l2_cache_backend
).
to
receive
(
:fetch
).
and_call_original
expect
(
subject
).
to
be_truthy
end
.
not_to
exceed_query_limit
(
2
)
end
.
not_to
exceed_query_limit
(
3
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment