Class: Namespace

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_AND_OVERRIDABLE =
'disabled_and_overridable'
SR_ENABLED =
'enabled'
SHARED_RUNNERS_SETTINGS =
[SR_DISABLED_AND_UNOVERRIDABLE, SR_DISABLED_AND_OVERRIDABLE, SR_ENABLED].freeze
URL_MAX_LENGTH =
255
STATISTICS_COLUMNS =
i[
  storage_size
  repository_size
  wiki_size
  snippets_size
  lfs_objects_size
  build_artifacts_size
  pipeline_artifacts_size
  packages_size
  uploads_size
].freeze

Constants included from Cells::Claimable

Cells::Claimable::CLAIMS_BUCKET_TYPE, Cells::Claimable::CLAIMS_SOURCE_TYPE, Cells::Claimable::CLAIMS_SUBJECT_TYPE, Cells::Claimable::MissingPrimaryKeyError

Constants included from BlocksUnsafeSerialization

BlocksUnsafeSerialization::UnsafeSerializationError

Constants included from Namespaces::Stateful

Namespaces::Stateful::STATES

Constants included from Namespaces::Traversal::Linear

Namespaces::Traversal::Linear::UnboundedSearch

Constants included from Gitlab::SQL::Pattern

Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING, Gitlab::SQL::Pattern::REGEX_QUOTED_TERM

Constants included from Gitlab::VisibilityLevel

Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::LEVELS_FOR_ADMINS, Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::PUBLIC

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from HasCheckConstraints

HasCheckConstraints::NOT_NULL_CHECK_PATTERN

Constants included from ResetOnColumnErrors

ResetOnColumnErrors::MAX_RESET_PERIOD

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Gitlab::Utils::Override

extended, extensions, included, method_added, override, prepended, queue_verification, verify!

Methods included from Cells::Claimable

#handle_grpc_error

Methods included from Referable

#referable_inspect, #reference_link_text

Methods included from Ci::NamespaceSettings

#allow_stale_runner_pruning=, #allow_stale_runner_pruning?

Methods included from BlocksUnsafeSerialization

#serializable_hash

Methods included from Organizations::Isolatable

#isolated?, #mark_as_isolated!, #mark_as_not_isolated!, #not_isolated?

Methods included from Namespaces::AdjournedDeletable

#ancestor_scheduled_for_deletion?, #deletion_adjourned_period, #deletion_in_progress_or_scheduled_in_hierarchy_chain?, #first_scheduled_for_deletion_in_hierarchy_chain, #scheduled_for_deletion_in_hierarchy_chain?, #self_deletion_scheduled?, #self_deletion_scheduled_deletion_created_on

Methods included from Namespaces::Traversal::Cached

#all_project_ids, #all_unarchived_project_ids, #descendant_ids, #self_and_descendant_ids

Methods included from Namespaces::Traversal::Linear

#all_project_ids, #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_path, #use_traversal_ids?

Methods included from Namespaces::Traversal::Recursive

#all_project_ids, #all_unarchived_project_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

Methods included from FeatureGate

#flipper_id

Methods included from Gitlab::SQL::Pattern

split_query_to_search_terms

Methods included from AfterCommitQueue

#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, #owned_by?

Methods included from Gitlab::VisibilityLevel

allowed_for?, allowed_level?, allowed_levels, allowed_levels_for_user, 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

Methods inherited from ApplicationRecord

===, cached_column_list, #create_or_load_association, current_transaction, declarative_enum, default_select_columns, delete_all_returning, #deleted_from_database?, id_in, id_not_in, iid_in, nullable_column?, 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

Methods included from Organizations::Sharding

#sharding_organization

Methods included from ResetOnColumnErrors

#reset_on_union_error, #reset_on_unknown_attribute_error

Methods included from Gitlab::SensitiveSerializableHash

#serializable_hash

Instance Attribute Details

#emails_enabled_memoized=(value) ⇒ Object (writeonly)

Make sure that the name is same as strong_memoize name in root_ancestor method



283
284
285
# File 'app/models/namespace.rb', line 283

def emails_enabled_memoized=(value)
  @emails_enabled_memoized = value
end

#root_ancestor=(value) ⇒ Object (writeonly)

Make sure that the name is same as strong_memoize name in root_ancestor method



283
284
285
# File 'app/models/namespace.rb', line 283

def root_ancestor=(value)
  @root_ancestor = value
end

Class Method Details

.by_path(path) ⇒ Object



299
300
301
# File 'app/models/namespace.rb', line 299

def by_path(path)
  find_by('lower(path) = :value', value: path.downcase)
end

.clean_path(path, limited_to: Namespace.all) ⇒ Object



381
382
383
384
385
# File 'app/models/namespace.rb', line 381

def clean_path(path, limited_to: Namespace.all)
  slug = Gitlab::Slug::Path.new(path).generate
  path = Namespaces::RandomizedSuffixPath.new(slug)
  Gitlab::Utils::Uniquify.new.string(path) { |s| limited_to.find_by_path_or_name(s) || ProjectSetting.unique_domain_exists?(s) }
end

.find_by_path_or_name(path) ⇒ Object

Case insensitive search for namespace by path or name



304
305
306
# File 'app/models/namespace.rb', line 304

def find_by_path_or_name(path)
  find_by("lower(path) = :path OR lower(name) = :path", path: path.downcase)
end

.find_top_levelObject



308
309
310
# File 'app/models/namespace.rb', line 308

def find_top_level
  top_level.take
end

.gfm_autocomplete_search(query) ⇒ Object



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'app/models/namespace.rb', line 357

def gfm_autocomplete_search(query)
  namespaces_cte = Gitlab::SQL::CTE.new(table_name, without_order)

  # This scope does not work with `ProjectNamespace` records because they don't have a corresponding `route` association.
  # We do not chain the `without_project_namespaces` scope because it results in an expensive query plan in certain cases
  unscoped
    .with(namespaces_cte.to_arel)
    .from(namespaces_cte.table)
    .joins(:route)
    .where(
      "REPLACE(routes.name, ' ', '') ILIKE :pattern OR routes.path ILIKE :pattern",
      pattern: "%#{sanitize_sql_like(query)}%"
    )
    .order(
      Arel.sql(sanitize_sql(
        [
          "CASE WHEN REPLACE(routes.name, ' ', '') ILIKE :prefix_pattern OR routes.path ILIKE :prefix_pattern THEN 1 ELSE 2 END",
          { prefix_pattern: "#{sanitize_sql_like(query)}%" }
        ]
      )),
      'routes.path'
    )
end

.reference_patternObject



391
392
393
# File 'app/models/namespace.rb', line 391

def reference_pattern
  User.reference_pattern
end

.reference_prefixObject



387
388
389
# File 'app/models/namespace.rb', line 387

def reference_prefix
  User.reference_prefix
end

.root_ids_for(namespace_ids) ⇒ Array<Integer>

Extracts root namespace IDs from a list of namespace IDs.

Parameters:

  • namespace_ids (Array<Integer>)

    List of namespace IDs

Returns:

  • (Array<Integer>)

    List of unique root namespace IDs



316
317
318
319
320
321
322
# File 'app/models/namespace.rb', line 316

def root_ids_for(namespace_ids)
  where(id: namespace_ids)
    .where.not(Arel.sql("traversal_ids[1]").eq(nil))
    .distinct
    .limit(1500) # the limit is higher than heaviest 100 requests. The majority is much less https://gitlab.com/gitlab-org/gitlab/-/issues/577678#note_2841315975 -
    .pluck(Arel.sql("traversal_ids[1]"))
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.



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'app/models/namespace.rb', line 331

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

.self_or_ancestors_archived_setting_subqueryObject



415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'app/models/namespace.rb', line 415

def self_or_ancestors_archived_setting_subquery
  namespace_setting_reflection = reflect_on_association(:namespace_settings)
  namespace_setting_table = Arel::Table.new(namespace_setting_reflection.table_name)
  traversal_ids_ref = "#{arel_table.name}.#{arel_table[:traversal_ids].name}"

  namespace_setting_table
    .project(1)
    .where(
      namespace_setting_table[namespace_setting_reflection.foreign_key]
        .eq(Arel.sql("ANY (#{traversal_ids_ref})"))
    )
    .where(namespace_setting_table[:archived].eq(true))
end

.sti_class_for(type_name) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
# File 'app/models/namespace.rb', line 286

def sti_class_for(type_name)
  case type_name
  when Group.sti_name
    Group
  when Namespaces::ProjectNamespace.sti_name
    Namespaces::ProjectNamespace
  when Namespaces::UserNamespace.sti_name
    Namespaces::UserNamespace
  else
    Namespace
  end
end

.sum_project_statistics_column(column) ⇒ Object



395
396
397
398
399
400
# File 'app/models/namespace.rb', line 395

def sum_project_statistics_column(column)
  sum = ProjectStatistics.arel_table[column].sum

  coalesce = Arel::Nodes::NamedFunction.new('COALESCE', [sum, 0])
  coalesce.as(column.to_s)
end

.username_reserved?(username) ⇒ Boolean

Returns:

  • (Boolean)


402
403
404
# File 'app/models/namespace.rb', line 402

def username_reserved?(username)
  without_project_namespaces.top_level.find_by_path_or_name(username).present?
end

.username_reserved_for_organization?(username, organization, excluding: []) ⇒ Boolean

Returns:

  • (Boolean)


406
407
408
409
410
411
412
413
# File 'app/models/namespace.rb', line 406

def username_reserved_for_organization?(username, organization, excluding: [])
  without_project_namespaces
    .top_level
    .in_organization(organization)
    .where.not(id: excluding)
    .find_by_path_or_name(username)
    .present?
end

Instance Method Details

#actual_limitsObject



730
731
732
733
734
735
# File 'app/models/namespace.rb', line 730

def actual_limits
  # We default to PlanLimits.new otherwise a lot of specs would fail
  # On production each plan should already have associated limits record
  # https://gitlab.com/gitlab-org/gitlab/issues/36037
  actual_plan.actual_limits
end

#actual_planObject



718
719
720
# File 'app/models/namespace.rb', line 718

def actual_plan
  Plan.default
end

#actual_plan_nameObject



737
738
739
# File 'app/models/namespace.rb', line 737

def actual_plan_name
  actual_plan.name
end

#aggregation_scheduled?Boolean

Returns:

  • (Boolean)


670
671
672
# File 'app/models/namespace.rb', line 670

def aggregation_scheduled?
  aggregation_schedule.present?
end

#all_active_project_idsObject



608
609
610
# File 'app/models/namespace.rb', line 608

def all_active_project_ids
  all_projects.not_aimed_for_deletion.non_archived.select(:id)
end

#all_ancestors_have_runner_registration_enabled?Boolean

Returns:

  • (Boolean)


812
813
814
# File 'app/models/namespace.rb', line 812

def all_ancestors_have_runner_registration_enabled?
  namespace_settings&.all_ancestors_have_runner_registration_enabled?
end

#all_catalog_resourcesObject



600
601
602
# File 'app/models/namespace.rb', line 600

def all_catalog_resources
  Ci::Catalog::Resource.where(project: all_projects)
end

#all_container_repositoriesObject



704
705
706
# File 'app/models/namespace.rb', line 704

def all_container_repositories
  ContainerRepository.for_project_id(all_projects)
end

#all_project_ids_except(ids) ⇒ Object



625
626
627
# File 'app/models/namespace.rb', line 625

def all_project_ids_except(ids)
  all_project_ids.where.not(id: ids)
end

#all_projectsObject

Includes projects from this namespace and projects from all subgroups that belongs to this namespace



595
596
597
598
# File 'app/models/namespace.rb', line 595

def all_projects
  namespace = user_namespace? ? self : self_and_descendant_ids
  Project.where(namespace: namespace)
end

#all_projects_except_soft_deletedObject



604
605
606
# File 'app/models/namespace.rb', line 604

def all_projects_except_soft_deleted
  all_projects.not_aimed_for_deletion
end

#all_projects_with_pagesObject



834
835
836
837
838
839
840
841
842
# File 'app/models/namespace.rb', line 834

def all_projects_with_pages
  all_projects.with_pages_deployed.includes(
    :route,
    :project_setting,
    :project_feature,
    :active_pages_deployments,
    :namespace
  )
end

#allow_runner_registration_token?Boolean

Returns:

  • (Boolean)


816
817
818
# File 'app/models/namespace.rb', line 816

def allow_runner_registration_token?
  !!namespace_settings&.allow_runner_registration_token?
end

#allowed_work_item_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


886
887
888
889
890
891
892
893
894
895
# File 'app/models/namespace.rb', line 886

def allowed_work_item_type?(type)
  type = type.to_s

  unless ::WorkItems::TypesFilter.base_types.include?(type)
    raise ArgumentError,
      %("#{type}" is not a valid WorkItems::Type.base_types)
  end

  allowed_work_item_types.include?(type)
end

#allowed_work_item_typesObject



881
882
883
# File 'app/models/namespace.rb', line 881

def allowed_work_item_types
  ::WorkItems::TypesFilter.new(container: self).allowed_types
end

#ancestors_archived?Boolean

Returns:

  • (Boolean)


447
448
449
# File 'app/models/namespace.rb', line 447

def ancestors_archived?
  ancestors.archived.exists?
end

#any_project_has_container_registry_tags?Boolean

Returns:

  • (Boolean)


493
494
495
# File 'app/models/namespace.rb', line 493

def any_project_has_container_registry_tags?
  first_project_with_container_registry_tags.present?
end

#any_project_with_pages_deployed?Boolean

Returns:

  • (Boolean)


708
709
710
# File 'app/models/namespace.rb', line 708

def any_project_with_pages_deployed?
  all_projects.with_pages_deployed.any?
end

#any_project_with_shared_runners_enabled?Boolean

Returns:

  • (Boolean)


585
586
587
# File 'app/models/namespace.rb', line 585

def any_project_with_shared_runners_enabled?
  projects.with_shared_runners_enabled.any?
end

#archived?Boolean Also known as: self_archived?

Returns:

  • (Boolean)


430
431
432
# File 'app/models/namespace.rb', line 430

def archived?
  !!namespace_settings&.archived?
end

#auto_devops_enabled?Boolean

Returns:

  • (Boolean)


652
653
654
# File 'app/models/namespace.rb', line 652

def auto_devops_enabled?
  first_auto_devops_config[:status]
end

#bot_user_namespace?Boolean

Returns:

  • (Boolean)


531
532
533
534
535
536
# File 'app/models/namespace.rb', line 531

def bot_user_namespace?
  return false unless user_namespace?
  return false unless owner && owner.bot?

  true
end

#certificate_based_clusters_enabled?Boolean

Returns:

  • (Boolean)


800
801
802
# File 'app/models/namespace.rb', line 800

def certificate_based_clusters_enabled?
  cluster_enabled_granted? || certificate_based_clusters_enabled_ff?
end

#changing_allow_descendants_override_disabled_shared_runners_is_allowedObject



749
750
751
752
753
754
755
756
757
758
759
# File 'app/models/namespace.rb', line 749

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_allowedObject



741
742
743
744
745
746
747
# File 'app/models/namespace.rb', line 741

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



712
713
714
715
716
# File 'app/models/namespace.rb', line 712

def closest_setting(name)
  self_and_ancestors(hierarchy_order: :asc)
    .find { |n| !n.read_attribute(name).nil? }
    .try(name)
end

#container_repositories_sizeObject



692
693
694
695
696
697
698
699
700
701
702
# File 'app/models/namespace.rb', line 692

def container_repositories_size
  strong_memoize(:container_repositories_size) do
    next unless root?
    next unless ContainerRegistry::GitlabApiClient.supports_gitlab_api?
    next 0 if all_container_repositories.empty?

    Rails.cache.fetch(container_repositories_size_cache_key, expires_in: 7.days) do
      ContainerRegistry::GitlabApiClient.deduplicated_size(full_path)
    end
  end
end

#container_repositories_size_cache_keyObject



688
689
690
# File 'app/models/namespace.rb', line 688

def container_repositories_size_cache_key
  "namespaces:#{id}:container_repositories_size"
end

#default_branch_protected?Boolean

Returns:

  • (Boolean)


567
568
569
# File 'app/models/namespace.rb', line 567

def default_branch_protected?
  Gitlab::Access::DefaultBranchProtection.new(default_branch_protection_settings).any?
end

#default_branch_protectionObject



467
468
469
# File 'app/models/namespace.rb', line 467

def default_branch_protection
  super || Gitlab::CurrentSettings.default_branch_protection
end

#default_branch_protection_settingsObject



471
472
473
474
475
476
477
478
479
# File 'app/models/namespace.rb', line 471

def default_branch_protection_settings
  return Gitlab::CurrentSettings.default_branch_protection_defaults if user_namespace?

  settings = default_branch_protection_defaults

  return settings unless settings.blank?

  Gitlab::CurrentSettings.default_branch_protection_defaults
end

#emails_disabled?Boolean

any ancestor can disable emails for all descendants

Returns:

  • (Boolean)


563
564
565
# File 'app/models/namespace.rb', line 563

def emails_disabled?
  !emails_enabled?
end

#emails_enabled?Boolean

Returns:

  • (Boolean)


571
572
573
574
575
576
577
578
# File 'app/models/namespace.rb', line 571

def emails_enabled?
  # If no namespace_settings, we can assume it has not changed from enabled
  return true unless namespace_settings

  strong_memoize(:emails_enabled_memoized) do
    namespace_settings.emails_enabled?
  end
end

#enabled_git_access_protocolObject



804
805
806
807
808
809
810
# File 'app/models/namespace.rb', line 804

def enabled_git_access_protocol
  # If the instance-level setting is enabled, we defer to that
  return ::Gitlab::CurrentSettings.enabled_git_access_protocol unless ::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?

  # Otherwise we use the stored setting on the group
  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.

Returns:

  • (Boolean)


630
631
632
# File 'app/models/namespace.rb', line 630

def feature_available?(feature, _user = nil)
  licensed_feature_available?(feature)
end

#find_fork_of(project) ⇒ Object



546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'app/models/namespace.rb', line 546

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_configObject



656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'app/models/namespace.rb', line 656

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_ownerObject



542
543
544
# File 'app/models/namespace.rb', line 542

def first_owner
  owner
end

#first_project_with_container_registry_tagsObject



497
498
499
500
501
502
503
# File 'app/models/namespace.rb', line 497

def first_project_with_container_registry_tags
  if Gitlab.com_except_jh? && ContainerRegistry::GitlabApiClient.supports_gitlab_api?
    ContainerRegistry::GitlabApiClient.one_project_with_container_registry_tag(full_path)
  else
    all_projects.includes(:container_repositories).find(&:has_container_registry_tags?)
  end
end

#full_path_before_last_saveObject



639
640
641
642
643
644
645
646
# File 'app/models/namespace.rb', line 639

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

Returns:

  • (Boolean)


518
519
520
# File 'app/models/namespace.rb', line 518

def group_namespace?
  type == Group.sti_name
end

#has_parent?Boolean

Returns:

  • (Boolean)


612
613
614
# File 'app/models/namespace.rb', line 612

def has_parent?
  parent_id.present? || parent.present?
end

#human_nameObject



489
490
491
# File 'app/models/namespace.rb', line 489

def human_name
  owner_name || path
end

#issue_repositioning_disabled?Boolean

Returns:

  • (Boolean)


796
797
798
# File 'app/models/namespace.rb', line 796

def issue_repositioning_disabled?
  Feature.enabled?(:block_issue_repositioning, self, type: :ops)
end

#kindObject



511
512
513
514
515
516
# File 'app/models/namespace.rb', line 511

def kind
  return 'group' if group_namespace?
  return 'project' if project_namespace?

  'user' # defaults to user
end

#lfs_enabled?Boolean

Returns:

  • (Boolean)


580
581
582
583
# File 'app/models/namespace.rb', line 580

def lfs_enabled?
  # User namespace will always default to the global setting
  Gitlab.config.lfs.enabled
end

#licensed_feature_available?(_feature) ⇒ Boolean

Overridden in EE::Namespace

Returns:

  • (Boolean)


635
636
637
# File 'app/models/namespace.rb', line 635

def licensed_feature_available?(_feature)
  false
end

#linked_to_subscription?Boolean

Returns:

  • (Boolean)


726
727
728
# File 'app/models/namespace.rb', line 726

def linked_to_subscription?
  paid?
end

#multiple_issue_boards_available?Boolean

Overridden on EE module

Returns:

  • (Boolean)


621
622
623
# File 'app/models/namespace.rb', line 621

def multiple_issue_boards_available?
  false
end

#namespace_detailsObject



870
871
872
# File 'app/models/namespace.rb', line 870

def namespace_details
  super.presence || build_namespace_details
end

#owner_entityObject

To help with polymorphism between Namespaces and Project both models answers to owner_entity, where -Namespaces::ProjectNamespace returns the #project -Namespaces::UserNamespace returns the #owner



678
679
680
# File 'app/models/namespace.rb', line 678

def owner_entity
  self
end

#owner_entity_nameObject

To help with polymorphism between Namespaces and Project both models answers to owner_entity_name



684
685
686
# File 'app/models/namespace.rb', line 684

def owner_entity_name
  self.class.sti_name.underscore.to_sym
end

#owner_required?Boolean

Returns:

  • (Boolean)


538
539
540
# File 'app/models/namespace.rb', line 538

def owner_required?
  user_namespace?
end

#package_settingsObject



463
464
465
# File 'app/models/namespace.rb', line 463

def package_settings
  package_setting_relation || build_package_setting_relation
end

#pages_access_control_forced_by_ancestor?Boolean

Returns:

  • (Boolean)


830
831
832
# File 'app/models/namespace.rb', line 830

def pages_access_control_forced_by_ancestor?
  pages_access_control_trie(ancestors)&.covered?(traversal_ids)
end

#pages_access_control_forced_by_self_or_ancestor?Boolean

Returns:

  • (Boolean)


826
827
828
# File 'app/models/namespace.rb', line 826

def pages_access_control_forced_by_self_or_ancestor?
  pages_access_control_trie(self_and_ancestors)&.covered?(traversal_ids)
end

#pages_access_control_trie(namespaces = self_and_descendants) ⇒ Object



820
821
822
823
824
# File 'app/models/namespace.rb', line 820

def pages_access_control_trie(namespaces = self_and_descendants)
  traversal_ids = namespaces.joins(:namespace_settings).where(namespace_settings: { force_pages_access_control: true }).map(&:traversal_ids)

  Namespaces::Traversal::TrieNode.build(traversal_ids)
end

#paid?Boolean

Returns:

  • (Boolean)


722
723
724
# File 'app/models/namespace.rb', line 722

def paid?
  root? && actual_plan.paid?
end

#pipeline_variables_default_roleObject



858
859
860
861
862
863
864
# File 'app/models/namespace.rb', line 858

def pipeline_variables_default_role
  return namespace_settings.pipeline_variables_default_role if namespace_settings.present?

  # We could have old namespaces that don't have an associated `namespace_settings` record.
  # To avoid returning `nil` we return the database-level default.
  NamespaceSetting.column_defaults['pipeline_variables_default_role']
end

#project_namespace?Boolean

Returns:

  • (Boolean)


522
523
524
# File 'app/models/namespace.rb', line 522

def project_namespace?
  type == Namespaces::ProjectNamespace.sti_name
end

#recent?Boolean

Returns:

  • (Boolean)


792
793
794
# File 'app/models/namespace.rb', line 792

def recent?
  created_at >= 90.days.ago
end

#refresh_project_authorizationsObject



648
649
650
# File 'app/models/namespace.rb', line 648

def refresh_project_authorizations
  owner.refresh_authorized_projects
end

#root?Boolean

Returns:

  • (Boolean)


788
789
790
# File 'app/models/namespace.rb', line 788

def root?
  !has_parent?
end

#self_deletion_in_progress?Boolean

Returns:

  • (Boolean)


850
851
852
# File 'app/models/namespace.rb', line 850

def self_deletion_in_progress?
  !!deleted_at
end

#self_or_ancestors_archived?Boolean

Returns:

  • (Boolean)


436
437
438
439
440
441
442
443
444
445
# File 'app/models/namespace.rb', line 436

def self_or_ancestors_archived?
  if association(:namespace_settings_with_ancestors_inherited_settings).loaded? &&
      namespace_settings_with_ancestors_inherited_settings
    return namespace_settings_with_ancestors_inherited_settings.archived
  end

  return namespace_settings&.archived.present? if parent_id.nil? # It's a top level, no need to check ancestors. Fixes N+1

  self_and_ancestors(skope: Namespace).archived.exists?
end

#send_update_instructionsObject



505
506
507
508
509
# File 'app/models/namespace.rb', line 505

def send_update_instructions
  projects.each do |project|
    project.send_move_instructions("#{full_path_before_last_save}/#{project.path}")
  end
end

#shared_runnersObject



784
785
786
# File 'app/models/namespace.rb', line 784

def shared_runners
  @shared_runners ||= shared_runners_enabled ? Ci::Runner.instance_type : Ci::Runner.none
end

#shared_runners_settingObject



761
762
763
764
765
766
767
768
769
# File 'app/models/namespace.rb', line 761

def shared_runners_setting
  if shared_runners_enabled
    SR_ENABLED
  elsif allow_descendants_override_disabled_shared_runners
    SR_DISABLED_AND_OVERRIDABLE
  else
    SR_DISABLED_AND_UNOVERRIDABLE
  end
end

#shared_runners_setting_higher_than?(other_setting) ⇒ Boolean

Returns:

  • (Boolean)


771
772
773
774
775
776
777
778
779
780
781
782
# File 'app/models/namespace.rb', line 771

def shared_runners_setting_higher_than?(other_setting)
  case other_setting
  when SR_ENABLED
    false
  when SR_DISABLED_AND_OVERRIDABLE
    shared_runners_setting == SR_ENABLED
  when SR_DISABLED_AND_UNOVERRIDABLE
    shared_runners_setting == SR_ENABLED || shared_runners_setting == SR_DISABLED_AND_OVERRIDABLE
  else
    raise ArgumentError
  end
end

#subgroup?Boolean

Returns:

  • (Boolean)


616
617
618
# File 'app/models/namespace.rb', line 616

def subgroup?
  has_parent?
end

#supports_work_items?Boolean

Returns:

  • (Boolean)


897
898
899
# File 'app/models/namespace.rb', line 897

def supports_work_items?
  allowed_work_item_types.present?
end

#to_paramObject



485
486
487
# File 'app/models/namespace.rb', line 485

def to_param
  full_path
end

#to_referenceObject



459
460
461
# File 'app/models/namespace.rb', line 459

def to_reference(*)
  "#{self.class.reference_prefix}#{full_path}"
end

#to_reference_base(from = nil, full: false, absolute_path: false) ⇒ Object



451
452
453
454
455
456
457
# File 'app/models/namespace.rb', line 451

def to_reference_base(from = nil, full: false, absolute_path: false)
  if full || cross_namespace_reference?(from)
    absolute_path ? "/#{full_path}" : full_path
  elsif cross_project_reference?(from)
    path
  end
end

#traversal_ids_as_sqlObject



866
867
868
# File 'app/models/namespace.rb', line 866

def traversal_ids_as_sql
  traversal_ids.join(',')
end

#uploads_sharding_keyObject



854
855
856
# File 'app/models/namespace.rb', line 854

def uploads_sharding_key
  { namespace_id: id }
end

#user_ids_for_project_authorizationsObject



589
590
591
# File 'app/models/namespace.rb', line 589

def user_ids_for_project_authorizations
  [owner_id]
end

#user_namespace?Boolean

Returns:

  • (Boolean)


526
527
528
529
# File 'app/models/namespace.rb', line 526

def user_namespace?
  # That last bit ensures we're considered a user namespace as a default
  type.nil? || type == Namespaces::UserNamespace.sti_name || !(group_namespace? || project_namespace?)
end

#user_role(user) ⇒ Object



874
875
876
877
878
879
# File 'app/models/namespace.rb', line 874

def user_role(user)
  return unless user && !user_namespace?

  user_access = max_member_access_for_user(user)
  Gitlab::Access.human_access(user_access)
end

#visibility_level_fieldObject



481
482
483
# File 'app/models/namespace.rb', line 481

def visibility_level_field
  :visibility_level
end

#web_url(only_path: nil) ⇒ Object



844
845
846
# File 'app/models/namespace.rb', line 844

def web_url(only_path: nil)
  Gitlab::UrlBuilder.build(self, only_path: only_path)
end