Class: Group
- Inherits:
-
Namespace
show all
- Extended by:
- Gitlab::Utils::Override
- Includes:
- AccessRequestable, AfterCommitQueue, Avatarable, BulkMemberAccessLoad, BulkUsersByEmailLoad, ChronicDurationAttribute, EachBatch, Gitlab::ConfigHelper, Gitlab::Utils::StrongMemoize, GroupAPICompatibility, GroupDescendant, LoadedInGroupList, Referable, RunnerTokenExpirationInterval, SelectForProjectAuthorization, TokenAuthenticatable, WithUploads
- Defined in:
- app/models/group.rb
Defined Under Namespace
Classes: CrmSettings
Constant Summary
Constants included
from WithUploads
WithUploads::FILE_UPLOADERS
Constants included
from Avatarable
Avatarable::ALLOWED_IMAGE_SCALER_WIDTHS, Avatarable::GROUP_AVATAR_SIZES, Avatarable::MAXIMUM_FILE_SIZE, Avatarable::PROJECT_AVATAR_SIZES, Avatarable::USER_AVATAR_SIZES
Constants inherited
from Namespace
Namespace::NUMBER_OF_ANCESTORS_ALLOWED, Namespace::PATH_TRAILING_VIOLATIONS, Namespace::SHARED_RUNNERS_SETTINGS, Namespace::SR_DISABLED_AND_UNOVERRIDABLE, Namespace::SR_DISABLED_WITH_OVERRIDE, Namespace::SR_ENABLED, Namespace::URL_MAX_LENGTH
BlocksUnsafeSerialization::UnsafeSerializationError
Namespaces::Traversal::Linear::UnboundedSearch
Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING, Gitlab::SQL::Pattern::REGEX_QUOTED_WORD
Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::PUBLIC
CacheMarkdownField::INVALIDATED_BY
ApplicationRecord::MAX_PLUCK
Instance Attribute Summary
Attributes inherited from Namespace
#emails_disabled_memoized, #root_ancestor
#skip_markdown_cache_validation
Class Method Summary
collapse
Instance Method Summary
collapse
-
#access_level_roles ⇒ Object
-
#access_level_values ⇒ Object
-
#access_request_approvers_to_be_notified ⇒ Object
-
#activity_path ⇒ Object
-
#add_developer(user, current_user = nil) ⇒ Object
-
#add_guest(user, current_user = nil) ⇒ Object
-
#add_maintainer(user, current_user = nil) ⇒ Object
-
#add_member(user, access_level, current_user: nil, expires_at: nil, ldap: false, blocking_refresh: true) ⇒ Object
-
#add_members(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil) ⇒ Object
-
#add_owner(user, current_user = nil) ⇒ Object
-
#add_reporter(user, current_user = nil) ⇒ Object
-
#adjourned_deletion? ⇒ Boolean
-
#all_owners_excluding_project_bots ⇒ Object
-
#authorizable_members_with_parents ⇒ Object
-
#blocked_owners ⇒ Object
-
#bots ⇒ Object
-
#ci_variables_for(ref, project, environment: nil) ⇒ Object
-
#crm_enabled? ⇒ Boolean
-
#default_branch_name ⇒ Object
-
#dependency_proxy_feature_available? ⇒ Boolean
-
#dependency_proxy_image_prefix ⇒ Object
-
#dependency_proxy_image_ttl_policy ⇒ Object
-
#dependency_proxy_setting ⇒ Object
-
#direct_and_indirect_members ⇒ Object
Returns all members that are part of the group, it's subgroups, and ancestor groups.
-
#direct_and_indirect_members_with_inactive ⇒ Object
-
#direct_and_indirect_users ⇒ Object
Returns all users that are members of the group because: 1.
-
#direct_and_indirect_users_with_inactive ⇒ Object
Returns all users (also inactive) that are members of the group because: 1.
-
#direct_members ⇒ Object
-
#enforced_runner_token_expiration_interval ⇒ Object
-
#execute_hooks(data, hooks_scope) ⇒ Object
-
#execute_integrations(data, hooks_scope) ⇒ Object
-
#export_archive_exists? ⇒ Boolean
-
#export_file ⇒ Object
-
#export_file_exists? ⇒ Boolean
-
#feature_available?(feature, user = nil) ⇒ Boolean
-
#first_owner ⇒ Object
-
#format_runners_token(token) ⇒ Object
-
#gitlab_deploy_token ⇒ Object
-
#group_feature ⇒ Object
-
#has_container_repository_including_subgroups? ⇒ Boolean
-
#has_maintainer?(user) ⇒ Boolean
-
#has_owner?(user) ⇒ Boolean
-
#has_project_with_service_desk_enabled? ⇒ Boolean
-
#hashed_storage?(_feature) ⇒ Boolean
-
#highest_group_member(user) ⇒ Object
-
#human_name ⇒ Object
-
#last_owner?(user) ⇒ Boolean
Check if user is a last owner of the group.
-
#ldap_synced? ⇒ Boolean
-
#lfs_enabled? ⇒ Boolean
-
#mattermost_team_params ⇒ Object
-
#max_member_access_for_user(user, only_concrete_membership: false) ⇒ Object
Return the highest access level for a user.
-
#member(user) ⇒ Object
-
#member?(user, min_access_level = Gitlab::Access::GUEST) ⇒ Boolean
-
#member_last_blocked_owner?(member) ⇒ Boolean
-
#member_last_owner?(member) ⇒ Boolean
-
#members_from_self_and_ancestors_with_effective_access_level ⇒ Object
-
#members_with_descendants ⇒ Object
-
#members_with_parents ⇒ Object
-
#membership_locked? ⇒ Boolean
-
#notification_email_for(user) ⇒ Object
-
#notification_settings(hierarchy_order: nil) ⇒ Object
Overrides notification_settings has_many association This allows to apply notification settings from parent groups to child groups and projects.
-
#notification_settings_for(user, hierarchy_order: nil) ⇒ Object
-
#open_issues_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#open_merge_requests_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#owned_by?(user) ⇒ Boolean
-
#packages_feature_enabled? ⇒ Boolean
-
#parent_allows_two_factor_authentication? ⇒ Boolean
-
#post_create_hook ⇒ Object
-
#post_destroy_hook ⇒ Object
-
#preload_shared_group_links ⇒ Object
-
#project_creation_level ⇒ Object
-
#project_users_with_descendants ⇒ Object
Returns all users that are members of projects belonging to the current group or sub-groups.
-
#refresh_members_authorized_projects(blocking: true, priority: UserProjectAccessChangedService::HIGH_PRIORITY, direct_members_only: false) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#refresh_project_authorizations ⇒ Object
-
#related_group_ids ⇒ Object
-
#runners_token ⇒ Object
each existing group needs to have a `runners_token`.
-
#self_and_ancestors_ids ⇒ Object
-
#self_and_descendants_ids ⇒ Object
-
#shared_with_group_links_visible_to_user(user) ⇒ Object
-
#single_blocked_owner? ⇒ Boolean
-
#subgroup_creation_level ⇒ Object
-
#supports_events? ⇒ Boolean
-
#system_hook_service ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#timelogs ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#to_reference(_from = nil, target_project: nil, full: nil) ⇒ Object
-
#update_shared_runners_setting!(state) ⇒ Object
-
#user_ids_for_project_authorizations ⇒ Object
-
#users_count ⇒ Object
-
#users_ids_of_direct_members ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#users_with_descendants ⇒ Object
-
#users_with_parents ⇒ Object
-
#visibility_level_allowed?(level = self.visibility_level) ⇒ Boolean
-
#visibility_level_allowed_by_parent?(level = self.visibility_level) ⇒ Boolean
-
#visibility_level_allowed_by_projects?(level = self.visibility_level) ⇒ Boolean
-
#visibility_level_allowed_by_sub_groups?(level = self.visibility_level) ⇒ Boolean
-
#web_url(only_path: nil) ⇒ Object
-
#work_items_feature_flag_enabled? ⇒ Boolean
extended, extensions, included, method_added, override, prepended, queue_verification, verify!
#effective_runner_token_expiration_interval, #effective_runner_token_expiration_interval_human_readable, #enforced_runner_token_expiration_interval_human_readable
#chronic_duration_attributes, #output_chronic_duration_attribute
#project_creation_level_str, #project_creation_level_str=, #subgroup_creation_level_str, #subgroup_creation_level_str=
#clear_memoization, #strong_memoize, #strong_memoized?
#retrieve_upload
#perform_fast_destroy
#run_after_commit, #run_after_commit_or_now
build_hierarchy, #hierarchy
#children_count, #guest_count, #member_count, #project_count, #subgroup_count
Methods included from Referable
#referable_inspect, #reference_link_text, #to_reference_base
Methods included from Avatarable
#avatar_path, #avatar_type, #uncached_avatar_path, #upload_paths
#request_access
#gitlab_config, #gitlab_config_features
Methods inherited from Namespace
#actual_limits, #actual_plan, #actual_plan_name, #aggregation_scheduled?, #all_container_repositories, #all_project_ids_except, #all_projects, #any_project_has_container_registry_tags?, #any_project_with_pages_deployed?, #any_project_with_shared_runners_enabled?, #auto_devops_enabled?, by_path, #certificate_based_clusters_enabled?, #changing_allow_descendants_override_disabled_shared_runners_is_allowed, #changing_shared_runners_enabled_is_allowed, clean_name, clean_path, #closest_setting, #container_repositories_size, #container_repositories_size_cache_key, #default_branch_protection, #emails_disabled?, #enabled_git_access_protocol, find_by_pages_host, find_by_path_or_name, #find_fork_of, #first_auto_devops_config, #first_project_with_container_registry_tags, #full_path_before_last_save, #group_namespace?, #has_parent?, #issue_repositioning_disabled?, #kind, #licensed_feature_available?, #multiple_issue_boards_available?, #owner_required?, #package_settings, #pages_virtual_domain, #paid?, #project_namespace?, #recent?, #root?, search, #send_update_instructions, #shared_runners, #shared_runners_setting, #shared_runners_setting_higher_than?, sti_class_for, #storage_enforcement_date, #subgroup?, #to_param, top_most, #user_namespace?, #visibility_level_field
#allow_stale_runner_pruning=, #allow_stale_runner_pruning?
#serializable_hash
#ancestor_ids, #ancestors, #ancestors_upto, #descendants, #root_ancestor, #self_and_ancestor_ids, #self_and_ancestors, #self_and_descendant_ids, #self_and_descendants, #self_and_hierarchy, #use_traversal_ids?, #use_traversal_ids_for_ancestors?, #use_traversal_ids_for_ancestors_upto?, #use_traversal_ids_for_root_ancestor?, #use_traversal_ids_for_self_and_hierarchy?
#ancestor_ids, #ancestors, #ancestors_upto, #descendants, #object_hierarchy, #root_ancestor, #self_and_ancestor_ids, #self_and_ancestors, #self_and_descendant_ids, #self_and_descendants, #self_and_hierarchy
#flipper_id
#move_dir, #prepare_for_destroy
#gitlab_shell
Methods included from Routable
#build_full_path, find_by_full_path, #full_name, #full_path, #full_path_components, #parent_loaded?, #route_loaded?
allowed_for?, allowed_level?, allowed_levels, closest_allowed_level, #internal?, level_name, level_value, levels_for_user, non_restricted_level?, options, #private?, #public?, public_visibility_restricted?, restricted_level?, string_level, string_options, string_values, valid_level?, #visibility, #visibility=, #visibility_attribute_present?, #visibility_attribute_value, #visibility_level_attributes, #visibility_level_previous_changes, #visibility_level_value
#attribute_invalidated?, #banzai_render_context, #cached_html_for, #cached_html_up_to_date?, #can_cache_field?, #invalidated_markdown_cache?, #latest_cached_markdown_version, #local_version, #mentionable_attributes_changed?, #mentioned_filtered_user_ids_for, #parent_user, #refresh_markdown_cache, #refresh_markdown_cache!, #rendered_field_content, #skip_project_check?, #store_mentions!, #updated_cached_html_for
cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order
#serializable_hash
Class Method Details
.get_ids_by_ids_or_paths(ids, paths) ⇒ Object
257
258
259
|
# File 'app/models/group.rb', line 257
def get_ids_by_ids_or_paths(ids, paths)
by_ids_or_paths(ids, paths).pluck(:id)
end
|
.ids_with_disabled_email(groups) ⇒ Object
Returns the ids of the passed group models where the `emails_disabled` column is set to true anywhere in the ancestor hierarchy.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
# File 'app/models/group.rb', line 239
def ids_with_disabled_email(groups)
inner_groups = Group.where('id = namespaces_with_emails_disabled.id')
inner_query = inner_groups
.self_and_ancestors
.where(emails_disabled: true)
.select('1')
.limit(1)
group_ids = Namespace
.from('(SELECT * FROM namespaces) as namespaces_with_emails_disabled')
.where(namespaces_with_emails_disabled: { id: groups })
.where('EXISTS (?)', inner_query)
.pluck(:id)
Set.new(group_ids)
end
|
.preset_root_ancestor_for(groups) ⇒ Object
This method can be used only if all groups have the same top-level group
230
231
232
233
234
235
|
# File 'app/models/group.rb', line 230
def preset_root_ancestor_for(groups)
return groups if groups.size < 2
root = groups.first.root_ancestor
groups.drop(1).each { |group| group.root_ancestor = root }
end
|
.public_or_visible_to_user(user) ⇒ Object
WARNING: This method should never be used on its own please do make sure the number of rows you are filtering is small enough for this query
199
200
201
202
203
204
205
206
207
|
# File 'app/models/group.rb', line 199
def public_or_visible_to_user(user)
return public_to_user unless user
public_for_user = public_to_user_arel(user)
visible_for_user = visible_to_user_arel(user)
public_or_visible = public_for_user.or(visible_for_user)
where(public_or_visible)
end
|
.reference_pattern ⇒ Object
.reference_prefix ⇒ Object
.select_for_project_authorization ⇒ Object
209
210
211
212
213
214
215
216
217
|
# File 'app/models/group.rb', line 209
def select_for_project_authorization
if current_scope.joins_values.include?(:shared_projects)
joins('INNER JOIN namespaces project_namespace ON project_namespace.id = projects.namespace_id')
.where(project_namespace: { share_with_group_lock: false })
.select("projects.id AS project_id", "LEAST(project_group_links.group_access, members.access_level) AS access_level")
else
super
end
end
|
.sort_by_attribute(method) ⇒ Object
178
179
180
181
182
183
184
185
186
|
# File 'app/models/group.rb', line 178
def sort_by_attribute(method)
if method == 'storage_size_desc'
reorder('storage_size DESC, namespaces.id DESC')
else
order_by(method)
end
end
|
.sti_name ⇒ Object
26
27
28
|
# File 'app/models/group.rb', line 26
def self.sti_name
'Group'
end
|
.without_integration(integration) ⇒ Object
219
220
221
222
223
224
225
226
|
# File 'app/models/group.rb', line 219
def without_integration(integration)
integrations = Integration
.select('1')
.where("#{Integration.table_name}.group_id = namespaces.id")
.where(type: integration.type)
where('NOT EXISTS (?)', integrations)
end
|
Instance Method Details
#access_level_roles ⇒ Object
#access_level_values ⇒ Object
786
787
788
|
# File 'app/models/group.rb', line 786
def access_level_values
access_level_roles.values
end
|
#access_request_approvers_to_be_notified ⇒ Object
#activity_path ⇒ Object
801
802
803
|
# File 'app/models/group.rb', line 801
def activity_path
Gitlab::Routing.url_helpers.activity_group_path(self)
end
|
#add_developer(user, current_user = nil) ⇒ Object
396
397
398
|
# File 'app/models/group.rb', line 396
def add_developer(user, current_user = nil)
add_member(user, :developer, current_user: current_user)
end
|
#add_guest(user, current_user = nil) ⇒ Object
388
389
390
|
# File 'app/models/group.rb', line 388
def add_guest(user, current_user = nil)
add_member(user, :guest, current_user: current_user)
end
|
#add_maintainer(user, current_user = nil) ⇒ Object
400
401
402
|
# File 'app/models/group.rb', line 400
def add_maintainer(user, current_user = nil)
add_member(user, :maintainer, current_user: current_user)
end
|
#add_member(user, access_level, current_user: nil, expires_at: nil, ldap: false, blocking_refresh: true) ⇒ Object
376
377
378
379
380
381
382
383
384
385
386
|
# File 'app/models/group.rb', line 376
def add_member(user, access_level, current_user: nil, expires_at: nil, ldap: false, blocking_refresh: true)
Members::Groups::CreatorService.add_member( self,
user,
access_level,
current_user: current_user,
expires_at: expires_at,
ldap: ldap,
blocking_refresh: blocking_refresh
)
end
|
#add_members(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil) ⇒ Object
364
365
366
367
368
369
370
371
372
373
374
|
# File 'app/models/group.rb', line 364
def add_members(users, access_level, current_user: nil, expires_at: nil, tasks_to_be_done: [], tasks_project_id: nil)
Members::Groups::CreatorService.add_members( self,
users,
access_level,
current_user: current_user,
expires_at: expires_at,
tasks_to_be_done: tasks_to_be_done,
tasks_project_id: tasks_project_id
)
end
|
#add_owner(user, current_user = nil) ⇒ Object
404
405
406
|
# File 'app/models/group.rb', line 404
def add_owner(user, current_user = nil)
add_member(user, :owner, current_user: current_user)
end
|
#add_reporter(user, current_user = nil) ⇒ Object
392
393
394
|
# File 'app/models/group.rb', line 392
def add_reporter(user, current_user = nil)
add_member(user, :reporter, current_user: current_user)
end
|
#adjourned_deletion? ⇒ Boolean
745
746
747
|
# File 'app/models/group.rb', line 745
def adjourned_deletion?
false
end
|
#all_owners_excluding_project_bots ⇒ Object
446
447
448
|
# File 'app/models/group.rb', line 446
def all_owners_excluding_project_bots
members_with_parents.owners.merge(User.without_project_bot)
end
|
#authorizable_members_with_parents ⇒ Object
529
530
531
532
533
534
535
536
537
538
539
540
541
|
# File 'app/models/group.rb', line 529
def authorizable_members_with_parents
source_ids =
if has_parent?
self_and_ancestors.reorder(nil).select(:id)
else
id
end
group_hierarchy_members = GroupMember.where(source_id: source_ids).select(*GroupMember.cached_column_list)
GroupMember.from_union([group_hierarchy_members,
members_from_self_and_ancestor_group_shares]).authorizable
end
|
#blocked_owners ⇒ Object
420
421
422
|
# File 'app/models/group.rb', line 420
def blocked_owners
members.blocked.where(access_level: Gitlab::Access::OWNER)
end
|
#bots ⇒ Object
683
684
685
|
# File 'app/models/group.rb', line 683
def bots
users.project_bot
end
|
#ci_variables_for(ref, project, environment: nil) ⇒ Object
663
664
665
666
667
668
669
|
# File 'app/models/group.rb', line 663
def ci_variables_for(ref, project, environment: nil)
cache_key = "ci_variables_for:group:#{self&.id}:project:#{project&.id}:ref:#{ref}:environment:#{environment}"
::Gitlab::SafeRequestStore.fetch(cache_key) do
uncached_ci_variables_for(ref, project, environment: environment)
end
end
|
#crm_enabled? ⇒ Boolean
833
834
835
|
# File 'app/models/group.rb', line 833
def crm_enabled?
crm_settings&.enabled?
end
|
#default_branch_name ⇒ Object
778
779
780
|
# File 'app/models/group.rb', line 778
def default_branch_name
namespace_settings&.default_branch_name
end
|
#dependency_proxy_feature_available? ⇒ Boolean
302
303
304
|
# File 'app/models/group.rb', line 302
def dependency_proxy_feature_available?
::Gitlab.config.dependency_proxy.enabled
end
|
#dependency_proxy_image_prefix ⇒ Object
#dependency_proxy_image_ttl_policy ⇒ Object
821
822
823
|
# File 'app/models/group.rb', line 821
def dependency_proxy_image_ttl_policy
super || build_dependency_proxy_image_ttl_policy
end
|
#dependency_proxy_setting ⇒ Object
825
826
827
|
# File 'app/models/group.rb', line 825
def dependency_proxy_setting
super || build_dependency_proxy_setting
end
|
#direct_and_indirect_members ⇒ Object
Returns all members that are part of the group, it's subgroups, and ancestor groups
573
574
575
576
577
|
# File 'app/models/group.rb', line 573
def direct_and_indirect_members
GroupMember
.active_without_invites_and_requests
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
end
|
#direct_and_indirect_members_with_inactive ⇒ Object
579
580
581
582
583
584
|
# File 'app/models/group.rb', line 579
def direct_and_indirect_members_with_inactive
GroupMember
.non_request
.non_invite
.where(source_id: self_and_hierarchy.reorder(nil).select(:id))
end
|
#direct_and_indirect_users ⇒ Object
Returns all users that are members of the group because:
-
They belong to the group
-
They belong to a project that belongs to the group
-
They belong to a sub-group or project in such sub-group
-
They belong to an ancestor group
603
604
605
606
607
608
609
610
|
# File 'app/models/group.rb', line 603
def direct_and_indirect_users
User.from_union([
User
.where(id: direct_and_indirect_members.select(:user_id))
.reorder(nil),
project_users_with_descendants
])
end
|
#direct_and_indirect_users_with_inactive ⇒ Object
Returns all users (also inactive) that are members of the group because:
-
They belong to the group
-
They belong to a project that belongs to the group
-
They belong to a sub-group or project in such sub-group
-
They belong to an ancestor group
617
618
619
620
621
622
623
624
|
# File 'app/models/group.rb', line 617
def direct_and_indirect_users_with_inactive
User.from_union([
User
.where(id: direct_and_indirect_members_with_inactive.select(:user_id))
.reorder(nil),
project_users_with_descendants
])
end
|
#direct_members ⇒ Object
523
524
525
526
527
|
# File 'app/models/group.rb', line 523
def direct_members
GroupMember.active_without_invites_and_requests
.non_minimal_access
.where(source_id: id)
end
|
#enforced_runner_token_expiration_interval ⇒ Object
841
842
843
844
845
846
847
848
849
850
|
# File 'app/models/group.rb', line 841
def enforced_runner_token_expiration_interval
all_parent_groups = Gitlab::ObjectHierarchy.new(Group.where(id: id)).ancestors
all_group_settings = NamespaceSetting.where(namespace_id: all_parent_groups)
group_interval = all_group_settings.where.not(subgroup_runner_token_expiration_interval: nil).minimum(:subgroup_runner_token_expiration_interval)&.seconds
[
Gitlab::CurrentSettings.group_runner_token_expiration_interval&.seconds,
group_interval
].compact.min
end
|
#execute_hooks(data, hooks_scope) ⇒ Object
749
750
751
752
|
# File 'app/models/group.rb', line 749
def execute_hooks(data, hooks_scope)
end
|
#execute_integrations(data, hooks_scope) ⇒ Object
754
755
756
757
|
# File 'app/models/group.rb', line 754
def execute_integrations(data, hooks_scope)
end
|
#export_archive_exists? ⇒ Boolean
741
742
743
|
# File 'app/models/group.rb', line 741
def export_archive_exists?
import_export_upload&.export_archive_exists?
end
|
#export_file ⇒ Object
737
738
739
|
# File 'app/models/group.rb', line 737
def export_file
import_export_upload&.export_file
end
|
#export_file_exists? ⇒ Boolean
733
734
735
|
# File 'app/models/group.rb', line 733
def export_file_exists?
import_export_upload&.export_file_exists?
end
|
#feature_available?(feature, user = nil) ⇒ Boolean
859
860
861
862
863
864
865
|
# File 'app/models/group.rb', line 859
def feature_available?(feature, user = nil)
if ::Groups::FeatureSetting.available_features.include?(feature)
group_feature.feature_available?(feature, user) else
super
end
end
|
#first_owner ⇒ Object
774
775
776
|
# File 'app/models/group.rb', line 774
def first_owner
owners.first || parent&.first_owner || owner
end
|
#gitlab_deploy_token ⇒ Object
867
868
869
870
871
|
# File 'app/models/group.rb', line 867
def gitlab_deploy_token
strong_memoize(:gitlab_deploy_token) do
deploy_tokens.gitlab_deploy_token
end
end
|
#group_feature ⇒ Object
829
830
831
|
# File 'app/models/group.rb', line 829
def group_feature
super || build_group_feature
end
|
#has_container_repository_including_subgroups? ⇒ Boolean
430
431
432
|
# File 'app/models/group.rb', line 430
def has_container_repository_including_subgroups?
::ContainerRepository.for_group_and_its_subgroups(self).exists?
end
|
#has_maintainer?(user) ⇒ Boolean
424
425
426
427
428
|
# File 'app/models/group.rb', line 424
def has_maintainer?(user)
return false unless user
members_with_parents.maintainers.exists?(user_id: user)
end
|
#has_owner?(user) ⇒ Boolean
414
415
416
417
418
|
# File 'app/models/group.rb', line 414
def has_owner?(user)
return false unless user
members_with_parents.owners.exists?(user_id: user)
end
|
#has_project_with_service_desk_enabled? ⇒ Boolean
797
798
799
|
# File 'app/models/group.rb', line 797
def has_project_with_service_desk_enabled?
Gitlab::ServiceDesk.supported? && all_projects.service_desk_enabled.exists?
end
|
#hashed_storage?(_feature) ⇒ Boolean
693
694
695
|
# File 'app/models/group.rb', line 693
def hashed_storage?(_feature)
false
end
|
#highest_group_member(user) ⇒ Object
679
680
681
|
# File 'app/models/group.rb', line 679
def highest_group_member(user)
GroupMember.where(source_id: self_and_ancestors_ids, user_id: user.id).order(:access_level).last
end
|
#human_name ⇒ Object
329
330
331
|
# File 'app/models/group.rb', line 329
def human_name
full_name
end
|
#last_owner?(user) ⇒ Boolean
Check if user is a last owner of the group. Excludes project_bots
436
437
438
|
# File 'app/models/group.rb', line 436
def last_owner?(user)
has_owner?(user) && all_owners_excluding_project_bots.size == 1
end
|
#ldap_synced? ⇒ Boolean
462
463
464
|
# File 'app/models/group.rb', line 462
def ldap_synced?
false
end
|
#lfs_enabled? ⇒ Boolean
353
354
355
356
357
358
|
# File 'app/models/group.rb', line 353
def lfs_enabled?
return false unless Gitlab.config.lfs.enabled
return Gitlab.config.lfs.enabled if self[:lfs_enabled].nil?
self[:lfs_enabled]
end
|
#mattermost_team_params ⇒ Object
653
654
655
656
657
658
659
660
661
|
# File 'app/models/group.rb', line 653
def mattermost_team_params
max_length = 59
{
name: path[0..max_length],
display_name: name[0..max_length],
type: public? ? 'O' : 'I' }
end
|
#max_member_access_for_user(user, only_concrete_membership: false) ⇒ Object
Return the highest access level for a user
A special case is handled here when the user is a GitLab admin which implies it has “OWNER” access everywhere, but should not officially appear as a member of a group unless specifically added to it
646
647
648
649
650
651
|
# File 'app/models/group.rb', line 646
def max_member_access_for_user(user, only_concrete_membership: false)
return GroupMember::NO_ACCESS unless user
return GroupMember::OWNER if user.can_admin_all_resources? && !only_concrete_membership
max_member_access([user.id])[user.id]
end
|
#member(user) ⇒ Object
671
672
673
674
675
676
677
|
# File 'app/models/group.rb', line 671
def member(user)
if group_members.loaded?
group_members.find { |gm| gm.user_id == user.id }
else
group_members.find_by(user_id: user)
end
end
|
#member?(user, min_access_level = Gitlab::Access::GUEST) ⇒ Boolean
408
409
410
411
412
|
# File 'app/models/group.rb', line 408
def member?(user, min_access_level = Gitlab::Access::GUEST)
return false unless user
max_member_access_for_user(user) >= min_access_level
end
|
#member_last_blocked_owner?(member) ⇒ Boolean
454
455
456
457
458
459
460
|
# File 'app/models/group.rb', line 454
def member_last_blocked_owner?(member)
return member.last_blocked_owner unless member.last_blocked_owner.nil?
return false if members_with_parents.owners.any?
single_blocked_owner? && blocked_owners.exists?(user_id: member.user)
end
|
#member_last_owner?(member) ⇒ Boolean
440
441
442
443
444
|
# File 'app/models/group.rb', line 440
def member_last_owner?(member)
return member.last_owner unless member.last_owner.nil?
last_owner?(member.user)
end
|
#members_from_self_and_ancestors_with_effective_access_level ⇒ Object
561
562
563
564
|
# File 'app/models/group.rb', line 561
def members_from_self_and_ancestors_with_effective_access_level
members_with_parents.select([:user_id, 'MAX(access_level) AS access_level'])
.group(:user_id)
end
|
#members_with_descendants ⇒ Object
566
567
568
569
570
|
# File 'app/models/group.rb', line 566
def members_with_descendants
GroupMember
.active_without_invites_and_requests
.where(source_id: self_and_descendants.reorder(nil).select(:id))
end
|
#members_with_parents ⇒ Object
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
|
# File 'app/models/group.rb', line 543
def members_with_parents
source_ids =
if has_parent?
self_and_ancestors.reorder(nil).select(:id)
else
id
end
group_hierarchy_members = GroupMember.active_without_invites_and_requests
.non_minimal_access
.where(source_id: source_ids)
.select(*GroupMember.cached_column_list)
GroupMember.from_union([group_hierarchy_members,
members_from_self_and_ancestor_group_shares])
end
|
#membership_locked? ⇒ Boolean
725
726
727
|
# File 'app/models/group.rb', line 725
def membership_locked?
false end
|
#notification_email_for(user) ⇒ Object
306
307
308
309
310
|
# File 'app/models/group.rb', line 306
def notification_email_for(user)
notification_settings = notification_settings_for(user, hierarchy_order: :asc)
notification_settings.find { |n| n.notification_email.present? }&.notification_email
end
|
#notification_settings(hierarchy_order: nil) ⇒ Object
Overrides notification_settings has_many association This allows to apply notification settings from parent groups to child groups and projects.
282
283
284
285
286
287
288
289
290
291
292
|
# File 'app/models/group.rb', line 282
def notification_settings(hierarchy_order: nil)
source_type = self.class.base_class.name
settings = NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids)
return settings unless hierarchy_order && self_and_ancestors_ids.length > 1
settings
.joins("LEFT JOIN (#{self_and_ancestors(hierarchy_order: hierarchy_order).to_sql}) AS ordered_groups ON notification_settings.source_id = ordered_groups.id")
.select('notification_settings.*, ordered_groups.depth AS depth')
.order("ordered_groups.depth #{hierarchy_order}")
end
|
#notification_settings_for(user, hierarchy_order: nil) ⇒ Object
294
295
296
|
# File 'app/models/group.rb', line 294
def notification_settings_for(user, hierarchy_order: nil)
notification_settings(hierarchy_order: hierarchy_order).where(user: user)
end
|
#open_issues_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
#open_merge_requests_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
#owned_by?(user) ⇒ Boolean
360
361
362
|
# File 'app/models/group.rb', line 360
def owned_by?(user)
owners.include?(user)
end
|
#packages_feature_enabled? ⇒ Boolean
298
299
300
|
# File 'app/models/group.rb', line 298
def packages_feature_enabled?
::Gitlab.config.packages.enabled
end
|
#parent_allows_two_factor_authentication? ⇒ Boolean
790
791
792
793
794
795
|
# File 'app/models/group.rb', line 790
def parent_allows_two_factor_authentication?
return true unless has_parent?
ancestor_settings = ancestors.find_by(parent_id: nil).namespace_settings
ancestor_settings.allow_mfa_for_subgroups
end
|
#post_create_hook ⇒ Object
466
467
468
469
470
|
# File 'app/models/group.rb', line 466
def post_create_hook
Gitlab::AppLogger.info("Group \"#{name}\" was created")
system_hook_service.execute_hooks_for(self, :create)
end
|
#post_destroy_hook ⇒ Object
472
473
474
475
476
|
# File 'app/models/group.rb', line 472
def post_destroy_hook
Gitlab::AppLogger.info("Group \"#{name}\" was removed")
system_hook_service.execute_hooks_for(self, :destroy)
end
|
#preload_shared_group_links ⇒ Object
759
760
761
762
|
# File 'app/models/group.rb', line 759
def preload_shared_group_links
preloader = ActiveRecord::Associations::Preloader.new
preloader.preload(self, shared_with_group_links: [shared_with_group: :route])
end
|
#project_creation_level ⇒ Object
713
714
715
|
# File 'app/models/group.rb', line 713
def project_creation_level
super || ::Gitlab::CurrentSettings.default_project_creation
end
|
#project_users_with_descendants ⇒ Object
Returns all users that are members of projects belonging to the current group or sub-groups
632
633
634
635
636
|
# File 'app/models/group.rb', line 632
def project_users_with_descendants
User
.joins(projects: :group)
.where(namespaces: { id: self_and_descendants.select(:id) })
end
|
#refresh_members_authorized_projects(blocking: true, priority: UserProjectAccessChangedService::HIGH_PRIORITY, direct_members_only: false) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
|
# File 'app/models/group.rb', line 485
def refresh_members_authorized_projects(
blocking: true,
priority: UserProjectAccessChangedService::HIGH_PRIORITY,
direct_members_only: false
)
user_ids = if direct_members_only
users_ids_of_direct_members
else
user_ids_for_project_authorizations
end
UserProjectAccessChangedService
.new(user_ids)
.execute(blocking: blocking, priority: priority)
end
|
#refresh_project_authorizations ⇒ Object
697
698
699
|
# File 'app/models/group.rb', line 697
def refresh_project_authorizations
refresh_members_authorized_projects(blocking: false)
end
|
687
688
689
690
691
|
# File 'app/models/group.rb', line 687
def related_group_ids
[id,
*ancestors.pluck(:id),
*shared_with_group_links.pluck(:shared_with_group_id)]
end
|
#runners_token ⇒ Object
each existing group needs to have a `runners_token`. we do this on read since migrating all existing groups is not a feasible solution.
704
705
706
|
# File 'app/models/group.rb', line 704
def runners_token
ensure_runners_token!
end
|
#self_and_ancestors_ids ⇒ Object
511
512
513
514
515
|
# File 'app/models/group.rb', line 511
def self_and_ancestors_ids
strong_memoize(:self_and_ancestors_ids) do
self_and_ancestors.pluck(:id)
end
end
|
#self_and_descendants_ids ⇒ Object
517
518
519
520
521
|
# File 'app/models/group.rb', line 517
def self_and_descendants_ids
strong_memoize(:self_and_descendants_ids) do
self_and_descendants.pluck(:id)
end
end
|
#shared_with_group_links_visible_to_user(user) ⇒ Object
837
838
839
|
# File 'app/models/group.rb', line 837
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
|
#single_blocked_owner? ⇒ Boolean
450
451
452
|
# File 'app/models/group.rb', line 450
def single_blocked_owner?
blocked_owners.size == 1
end
|
#subgroup_creation_level ⇒ Object
#supports_events? ⇒ Boolean
729
730
731
|
# File 'app/models/group.rb', line 729
def supports_events?
false
end
|
#system_hook_service ⇒ Object
rubocop: disable CodeReuse/ServiceClass
479
480
481
|
# File 'app/models/group.rb', line 479
def system_hook_service
SystemHooksService.new
end
|
#timelogs ⇒ Object
rubocop: enable CodeReuse/ServiceClass
817
818
819
|
# File 'app/models/group.rb', line 817
def timelogs
Timelog.in_group(self)
end
|
#to_reference(_from = nil, target_project: nil, full: nil) ⇒ Object
312
313
314
|
# File 'app/models/group.rb', line 312
def to_reference(_from = nil, target_project: nil, full: nil)
"#{self.class.reference_prefix}#{full_path}"
end
|
#update_shared_runners_setting!(state) ⇒ Object
#user_ids_for_project_authorizations ⇒ Object
507
508
509
|
# File 'app/models/group.rb', line 507
def user_ids_for_project_authorizations
members_with_parents.pluck(Arel.sql('DISTINCT members.user_id'))
end
|
#users_count ⇒ Object
626
627
628
|
# File 'app/models/group.rb', line 626
def users_count
members.count
end
|
#users_ids_of_direct_members ⇒ Object
rubocop: enable CodeReuse/ServiceClass
503
504
505
|
# File 'app/models/group.rb', line 503
def users_ids_of_direct_members
direct_members.pluck(:user_id)
end
|
#users_with_descendants ⇒ Object
592
593
594
595
596
|
# File 'app/models/group.rb', line 592
def users_with_descendants
User
.where(id: members_with_descendants.select(:user_id))
.reorder(nil)
end
|
#users_with_parents ⇒ Object
586
587
588
589
590
|
# File 'app/models/group.rb', line 586
def users_with_parents
User
.where(id: members_with_parents.select(:user_id))
.reorder(nil)
end
|
#visibility_level_allowed?(level = self.visibility_level) ⇒ Boolean
347
348
349
350
351
|
# File 'app/models/group.rb', line 347
def visibility_level_allowed?(level = self.visibility_level)
visibility_level_allowed_by_parent?(level) &&
visibility_level_allowed_by_projects?(level) &&
visibility_level_allowed_by_sub_groups?(level)
end
|
#visibility_level_allowed_by_parent?(level = self.visibility_level) ⇒ Boolean
333
334
335
336
337
|
# File 'app/models/group.rb', line 333
def visibility_level_allowed_by_parent?(level = self.visibility_level)
return true unless parent_id && parent_id.nonzero?
level <= parent.visibility_level
end
|
#visibility_level_allowed_by_projects?(level = self.visibility_level) ⇒ Boolean
339
340
341
|
# File 'app/models/group.rb', line 339
def visibility_level_allowed_by_projects?(level = self.visibility_level)
!projects.where('visibility_level > ?', level).exists?
end
|
#visibility_level_allowed_by_sub_groups?(level = self.visibility_level) ⇒ Boolean
343
344
345
|
# File 'app/models/group.rb', line 343
def visibility_level_allowed_by_sub_groups?(level = self.visibility_level)
!children.where('visibility_level > ?', level).exists?
end
|
#web_url(only_path: nil) ⇒ Object
316
317
318
|
# File 'app/models/group.rb', line 316
def web_url(only_path: nil)
Gitlab::UrlBuilder.build(self, only_path: only_path)
end
|
#work_items_feature_flag_enabled? ⇒ Boolean
852
853
854
|
# File 'app/models/group.rb', line 852
def work_items_feature_flag_enabled?
feature_flag_enabled_for_self_or_ancestor?(:work_items)
end
|