Class: Namespace
- Inherits:
-
ApplicationRecord
show all
- Includes:
- AfterCommitQueue, BlocksUnsafeSerialization, CacheMarkdownField, Ci::NamespaceSettings, CrossDatabaseIgnoredTables, EachBatch, FeatureGate, FromUnion, Gitlab::SQL::Pattern, Gitlab::Utils::StrongMemoize, Gitlab::VisibilityLevel, Namespaces::Traversal::Linear, Namespaces::Traversal::Recursive, Referable, Routable, Sortable, Storage::LegacyNamespace
- Defined in:
- app/models/namespace/traversal_hierarchy.rb,
app/models/namespace.rb
Overview
A Namespace::TraversalHierarchy is the collection of namespaces that descend from a root Namespace as defined by the Namespace#traversal_ids attributes.
This class provides operations to be performed on the hierarchy itself, rather than individual namespaces.
This includes methods for synchronizing traversal_ids attributes to a correct state. We use recursive methods to determine the correct state so we don’t have to depend on the integrity of the traversal_ids attribute values themselves.
Defined Under Namespace
Classes: AdminNote, AggregationSchedule, Detail, PackageSetting, PackageSettingPolicy, PackageSettingsType, RootStorageStatistics, RootStorageStatisticsPolicy, SharedRunnersSettingEnum, TraversalHierarchy
Constant Summary
collapse
- NUMBER_OF_ANCESTORS_ALLOWED =
Prevent users from creating unreasonably deep level of nesting. The number 20 was taken based on maximum nesting level of Android repo (15) + some extra backup.
20
- SR_DISABLED_AND_UNOVERRIDABLE =
'disabled_and_unoverridable'
- SR_DISABLED_WITH_OVERRIDE =
DISABLED_WITH_OVERRIDE is deprecated in favour of DISABLED_AND_OVERRIDABLE.
'disabled_with_override'
- SR_DISABLED_AND_OVERRIDABLE =
'disabled_and_overridable'
- SR_ENABLED =
'enabled'
- SHARED_RUNNERS_SETTINGS =
[SR_DISABLED_AND_UNOVERRIDABLE, SR_DISABLED_WITH_OVERRIDE, SR_DISABLED_AND_OVERRIDABLE, SR_ENABLED].freeze
- URL_MAX_LENGTH =
255
BlocksUnsafeSerialization::UnsafeSerializationError
Namespaces::Traversal::Linear::UnboundedSearch
Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING, Gitlab::SQL::Pattern::REGEX_QUOTED_TERM
Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::PUBLIC
CacheMarkdownField::INVALIDATED_BY
ApplicationRecord::MAX_PLUCK
ResetOnUnionError::MAX_RESET_PERIOD
Instance Attribute Summary collapse
#skip_markdown_cache_validation
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Referable
#referable_inspect, #reference_link_text
#allow_stale_runner_pruning=, #allow_stale_runner_pruning?
#serializable_hash
#extended, extensions, #included, #method_added, #override, #prepended, #queue_verification, verify!
#ancestor_ids, #ancestors, #ancestors_upto, #descendants, #parent=, #parent_id=, #root_ancestor, #self_and_ancestor_ids, #self_and_ancestors, #self_and_descendant_ids, #self_and_descendants, #self_and_hierarchy, #traversal_ids, #traversal_ids=, #use_traversal_ids?
#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
split_query_to_search_terms
#move_dir, #prepare_for_destroy
#gitlab_shell
#run_after_commit, #run_after_commit_or_now
Methods included from Routable
#build_full_path, find_by_full_path, #full_name, #full_path, #full_path_components, optimize_routable_enabled?, #owned_by?, #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
Instance Attribute Details
#emails_disabled_memoized=(value) ⇒ Object
Make sure that the name is same as strong_memoize name in root_ancestor method
208
209
210
|
# File 'app/models/namespace.rb', line 208
def emails_disabled_memoized=(value)
@emails_disabled_memoized = value
end
|
#root_ancestor=(value) ⇒ Object
Make sure that the name is same as strong_memoize name in root_ancestor method
208
209
210
|
# File 'app/models/namespace.rb', line 208
def root_ancestor=(value)
@root_ancestor = value
end
|
Class Method Details
.by_path(path) ⇒ Object
224
225
226
|
# File 'app/models/namespace.rb', line 224
def by_path(path)
find_by('lower(path) = :value', value: path.downcase)
end
|
.clean_name(value) ⇒ Object
.clean_path(path, limited_to: Namespace.all) ⇒ Object
.find_by_path_or_name(path) ⇒ Object
Case insensitive search for namespace by path or name
229
230
231
|
# File 'app/models/namespace.rb', line 229
def find_by_path_or_name(path)
find_by("lower(path) = :path OR lower(name) = :path", path: path.downcase)
end
|
.reference_pattern ⇒ Object
.reference_prefix ⇒ Object
277
278
279
|
# File 'app/models/namespace.rb', line 277
def reference_prefix
User.reference_prefix
end
|
.search(query, include_parents: false, use_minimum_char_limit: true, exact_matches_first: false) ⇒ Object
Searches for namespaces matching the given query.
This method uses ILIKE on PostgreSQL.
query - The search query as a String.
Returns an ActiveRecord::Relation.
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# File 'app/models/namespace.rb', line 240
def search(query, include_parents: false, use_minimum_char_limit: true, exact_matches_first: false)
if include_parents
route_columns = [Route.arel_table[:path], Route.arel_table[:name]]
namespaces = without_project_namespaces
.where(id: Route.for_routable_type(Namespace.name)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046")
.fuzzy_search(query, route_columns,
use_minimum_char_limit: use_minimum_char_limit)
.select(:source_id))
if exact_matches_first
namespaces = namespaces
.joins(:route)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046")
.order(exact_matches_first_sql(query, route_columns))
end
namespaces
else
without_project_namespaces.fuzzy_search(query, [:path, :name], use_minimum_char_limit: use_minimum_char_limit, exact_matches_first: exact_matches_first)
end
end
|
.sti_class_for(type_name) ⇒ Object
.top_most ⇒ Object
273
274
275
|
# File 'app/models/namespace.rb', line 273
def top_most
by_parent(nil)
end
|
Instance Method Details
#actual_limits ⇒ Object
535
536
537
538
539
540
|
# File 'app/models/namespace.rb', line 535
def actual_limits
actual_plan.actual_limits
end
|
#actual_plan ⇒ Object
523
524
525
|
# File 'app/models/namespace.rb', line 523
def actual_plan
Plan.default
end
|
#actual_plan_name ⇒ Object
542
543
544
|
# File 'app/models/namespace.rb', line 542
def actual_plan_name
actual_plan.name
end
|
#aggregation_scheduled? ⇒ Boolean
487
488
489
|
# File 'app/models/namespace.rb', line 487
def aggregation_scheduled?
aggregation_schedule.present?
end
|
#all_ancestors_have_runner_registration_enabled? ⇒ Boolean
617
618
619
|
# File 'app/models/namespace.rb', line 617
def all_ancestors_have_runner_registration_enabled?
namespace_settings&.all_ancestors_have_runner_registration_enabled?
end
|
#all_container_repositories ⇒ Object
509
510
511
|
# File 'app/models/namespace.rb', line 509
def all_container_repositories
ContainerRepository.for_project_id(all_projects)
end
|
#all_project_ids ⇒ Object
438
439
440
|
# File 'app/models/namespace.rb', line 438
def all_project_ids
all_projects.pluck(:id)
end
|
#all_project_ids_except(ids) ⇒ Object
442
443
444
|
# File 'app/models/namespace.rb', line 442
def all_project_ids_except(ids)
all_projects.where.not(id: ids).pluck(:id)
end
|
#all_projects ⇒ Object
Includes projects from this namespace and projects from all subgroups that belongs to this namespace
414
415
416
417
|
# File 'app/models/namespace.rb', line 414
def all_projects
namespace = user_namespace? ? self : self_and_descendant_ids
Project.where(namespace: namespace)
end
|
#all_projects_except_soft_deleted ⇒ Object
Includes projects from this namespace and projects from all subgroups that belongs to this namespace, except the ones that are soft deleted
421
422
423
|
# File 'app/models/namespace.rb', line 421
def all_projects_except_soft_deleted
all_projects.not_aimed_for_deletion
end
|
#all_projects_with_pages ⇒ Object
625
626
627
628
629
630
631
632
|
# File 'app/models/namespace.rb', line 625
def all_projects_with_pages
all_projects.with_pages_deployed.includes(
:route,
:project_setting,
:project_feature,
pages_metadatum: :pages_deployment
)
end
|
#allow_runner_registration_token? ⇒ Boolean
621
622
623
|
# File 'app/models/namespace.rb', line 621
def allow_runner_registration_token?
!!namespace_settings&.allow_runner_registration_token?
end
|
315
316
317
|
# File 'app/models/namespace.rb', line 315
def any_project_has_container_registry_tags?
first_project_with_container_registry_tags.present?
end
|
#any_project_with_pages_deployed? ⇒ Boolean
513
514
515
|
# File 'app/models/namespace.rb', line 513
def any_project_with_pages_deployed?
all_projects.with_pages_deployed.any?
end
|
#any_project_with_shared_runners_enabled? ⇒ Boolean
404
405
406
|
# File 'app/models/namespace.rb', line 404
def any_project_with_shared_runners_enabled?
projects.with_shared_runners_enabled.any?
end
|
#auto_devops_enabled? ⇒ Boolean
469
470
471
|
# File 'app/models/namespace.rb', line 469
def auto_devops_enabled?
first_auto_devops_config[:status]
end
|
#bot_user_namespace? ⇒ Boolean
353
354
355
356
357
358
|
# File 'app/models/namespace.rb', line 353
def bot_user_namespace?
return false unless user_namespace?
return false unless owner && owner.bot?
true
end
|
#certificate_based_clusters_enabled? ⇒ Boolean
605
606
607
|
# File 'app/models/namespace.rb', line 605
def certificate_based_clusters_enabled?
cluster_enabled_granted? || certificate_based_clusters_enabled_ff?
end
|
#changing_allow_descendants_override_disabled_shared_runners_is_allowed ⇒ Object
554
555
556
557
558
559
560
561
562
563
564
|
# File 'app/models/namespace.rb', line 554
def changing_allow_descendants_override_disabled_shared_runners_is_allowed
return unless new_record? || changes.has_key?(:allow_descendants_override_disabled_shared_runners)
if shared_runners_enabled && allow_descendants_override_disabled_shared_runners
errors.add(:allow_descendants_override_disabled_shared_runners, _('can not be true if shared runners are enabled'))
end
if allow_descendants_override_disabled_shared_runners && has_parent? && parent.shared_runners_setting == SR_DISABLED_AND_UNOVERRIDABLE
errors.add(:allow_descendants_override_disabled_shared_runners, _('cannot be enabled because parent group does not allow it'))
end
end
|
#changing_shared_runners_enabled_is_allowed ⇒ Object
546
547
548
549
550
551
552
|
# File 'app/models/namespace.rb', line 546
def changing_shared_runners_enabled_is_allowed
return unless new_record? || changes.has_key?(:shared_runners_enabled)
if shared_runners_enabled && has_parent? && parent.shared_runners_setting == SR_DISABLED_AND_UNOVERRIDABLE
errors.add(:shared_runners_enabled, _('cannot be enabled because parent group has shared Runners disabled'))
end
end
|
#closest_setting(name) ⇒ Object
517
518
519
520
521
|
# File 'app/models/namespace.rb', line 517
def closest_setting(name)
self_and_ancestors(hierarchy_order: :asc)
.find { |n| !n.read_attribute(name).nil? }
.try(name)
end
|
#container_repositories_size ⇒ Object
#container_repositories_size_cache_key ⇒ Object
491
492
493
|
# File 'app/models/namespace.rb', line 491
def container_repositories_size_cache_key
"namespaces:#{id}:container_repositories_size"
end
|
#default_branch_protection ⇒ Object
299
300
301
|
# File 'app/models/namespace.rb', line 299
def default_branch_protection
super || Gitlab::CurrentSettings.default_branch_protection
end
|
#emails_disabled? ⇒ Boolean
any ancestor can disable emails for all descendants
385
386
387
388
389
390
391
392
393
|
# File 'app/models/namespace.rb', line 385
def emails_disabled?
strong_memoize(:emails_disabled_memoized) do
if parent_id
self_and_ancestors.where(emails_disabled: true).exists?
else
!!emails_disabled
end
end
end
|
#emails_enabled? ⇒ Boolean
395
396
397
|
# File 'app/models/namespace.rb', line 395
def emails_enabled?
!emails_disabled?
end
|
#enabled_git_access_protocol ⇒ Object
609
610
611
612
613
614
615
|
# File 'app/models/namespace.rb', line 609
def enabled_git_access_protocol
return ::Gitlab::CurrentSettings.enabled_git_access_protocol unless ::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
namespace_settings&.enabled_git_access_protocol
end
|
#feature_available?(feature, _user = nil) ⇒ Boolean
Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn’t used anymore.
447
448
449
|
# File 'app/models/namespace.rb', line 447
def feature_available?(feature, _user = nil)
licensed_feature_available?(feature)
end
|
#find_fork_of(project) ⇒ Object
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|
# File 'app/models/namespace.rb', line 368
def find_fork_of(project)
return unless project.fork_network
if Gitlab::SafeRequestStore.active?
forks_in_namespace = Gitlab::SafeRequestStore.fetch("namespaces:#{id}:forked_projects") do
Hash.new do |found_forks, project|
found_forks[project] = project.fork_network.find_forks_in(projects).first
end
end
forks_in_namespace[project]
else
project.fork_network.find_forks_in(projects).first
end
end
|
#first_auto_devops_config ⇒ Object
473
474
475
476
477
478
479
480
481
482
483
484
485
|
# File 'app/models/namespace.rb', line 473
def first_auto_devops_config
return { scope: :group, status: auto_devops_enabled } unless auto_devops_enabled.nil?
strong_memoize(:first_auto_devops_config) do
if parent.present?
Rails.cache.fetch(first_auto_devops_config_cache_key_for(id), expires_in: 1.day) do
parent.first_auto_devops_config
end
else
{ scope: :instance, status: Gitlab::CurrentSettings.auto_devops_enabled? }
end
end
end
|
#first_owner ⇒ Object
364
365
366
|
# File 'app/models/namespace.rb', line 364
def first_owner
owner
end
|
#full_path_before_last_save ⇒ Object
456
457
458
459
460
461
462
463
|
# File 'app/models/namespace.rb', line 456
def full_path_before_last_save
if parent_id_before_last_save.nil?
path_before_last_save
else
previous_parent = Group.find_by(id: parent_id_before_last_save)
previous_parent.full_path + '/' + path_before_last_save
end
end
|
#group_namespace? ⇒ Boolean
340
341
342
|
# File 'app/models/namespace.rb', line 340
def group_namespace?
type == Group.sti_name
end
|
#has_parent? ⇒ Boolean
425
426
427
|
# File 'app/models/namespace.rb', line 425
def has_parent?
parent_id.present? || parent.present?
end
|
#human_name ⇒ Object
311
312
313
|
# File 'app/models/namespace.rb', line 311
def human_name
owner_name
end
|
#issue_repositioning_disabled? ⇒ Boolean
601
602
603
|
# File 'app/models/namespace.rb', line 601
def issue_repositioning_disabled?
Feature.enabled?(:block_issue_repositioning, self, type: :ops)
end
|
#kind ⇒ Object
333
334
335
336
337
338
|
# File 'app/models/namespace.rb', line 333
def kind
return 'group' if group_namespace?
return 'project' if project_namespace?
'user' end
|
#lfs_enabled? ⇒ Boolean
399
400
401
402
|
# File 'app/models/namespace.rb', line 399
def lfs_enabled?
Gitlab.config.lfs.enabled
end
|
#licensed_feature_available?(_feature) ⇒ Boolean
Overridden in EE::Namespace
452
453
454
|
# File 'app/models/namespace.rb', line 452
def licensed_feature_available?(_feature)
false
end
|
#multiple_issue_boards_available? ⇒ Boolean
434
435
436
|
# File 'app/models/namespace.rb', line 434
def multiple_issue_boards_available?
false
end
|
#owner_required? ⇒ Boolean
360
361
362
|
# File 'app/models/namespace.rb', line 360
def owner_required?
user_namespace?
end
|
#package_settings ⇒ Object
295
296
297
|
# File 'app/models/namespace.rb', line 295
def package_settings
package_setting_relation || build_package_setting_relation
end
|
#paid? ⇒ Boolean
527
528
529
|
# File 'app/models/namespace.rb', line 527
def paid?
root? && actual_plan.paid?
end
|
#prevent_delete? ⇒ Boolean
531
532
533
|
# File 'app/models/namespace.rb', line 531
def prevent_delete?
paid?
end
|
#project_namespace? ⇒ Boolean
#recent? ⇒ Boolean
597
598
599
|
# File 'app/models/namespace.rb', line 597
def recent?
created_at >= 90.days.ago
end
|
#refresh_project_authorizations ⇒ Object
465
466
467
|
# File 'app/models/namespace.rb', line 465
def refresh_project_authorizations
owner.refresh_authorized_projects
end
|
#root? ⇒ Boolean
593
594
595
|
# File 'app/models/namespace.rb', line 593
def root?
!has_parent?
end
|
#send_update_instructions ⇒ Object
327
328
329
330
331
|
# File 'app/models/namespace.rb', line 327
def send_update_instructions
projects.each do |project|
project.send_move_instructions("#{full_path_before_last_save}/#{project.path}")
end
end
|
#shared_runners ⇒ Object
589
590
591
|
# File 'app/models/namespace.rb', line 589
def shared_runners
@shared_runners ||= shared_runners_enabled ? Ci::Runner.instance_type : Ci::Runner.none
end
|
#shared_runners_setting ⇒ Object
#shared_runners_setting_higher_than?(other_setting) ⇒ Boolean
#subgroup? ⇒ Boolean
429
430
431
|
# File 'app/models/namespace.rb', line 429
def subgroup?
has_parent?
end
|
#to_param ⇒ Object
307
308
309
|
# File 'app/models/namespace.rb', line 307
def to_param
full_path
end
|
#to_reference ⇒ Object
291
292
293
|
# File 'app/models/namespace.rb', line 291
def to_reference(*)
"#{self.class.reference_prefix}#{full_path}"
end
|
#to_reference_base(from = nil, full: false) ⇒ Object
286
287
288
289
|
# File 'app/models/namespace.rb', line 286
def to_reference_base(from = nil, full: false)
return full_path if full || cross_namespace_reference?(from)
return path if cross_project_reference?(from)
end
|
#user_ids_for_project_authorizations ⇒ Object
408
409
410
|
# File 'app/models/namespace.rb', line 408
def user_ids_for_project_authorizations
[owner_id]
end
|
#user_namespace? ⇒ Boolean
348
349
350
351
|
# File 'app/models/namespace.rb', line 348
def user_namespace?
type.nil? || type == Namespaces::UserNamespace.sti_name || !(group_namespace? || project_namespace?)
end
|
#visibility_level_field ⇒ Object
303
304
305
|
# File 'app/models/namespace.rb', line 303
def visibility_level_field
:visibility_level
end
|