Commit dab58c88 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '337102-backfill-usernamespace-for-every-personal-namespace' into 'master'

Ensure code can handle both UserNamespace and type == nil namespaces

See merge request gitlab-org/gitlab!68894
parents 5bf2452f 4804df2e
...@@ -101,7 +101,9 @@ class Namespace < ApplicationRecord ...@@ -101,7 +101,9 @@ class Namespace < ApplicationRecord
saved_change_to_name? || saved_change_to_path? || saved_change_to_parent_id? saved_change_to_name? || saved_change_to_path? || saved_change_to_parent_id?
} }
scope :for_user, -> { where(type: nil) } # TODO: change to `type: Namespaces::UserNamespace.sti_name` when
# working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
scope :user_namespaces, -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) }
scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) } scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) }
scope :include_route, -> { includes(:route) } scope :include_route, -> { includes(:route) }
scope :by_parent, -> (parent) { where(parent_id: parent) } scope :by_parent, -> (parent) { where(parent_id: parent) }
...@@ -143,9 +145,7 @@ class Namespace < ApplicationRecord ...@@ -143,9 +145,7 @@ class Namespace < ApplicationRecord
when Namespaces::ProjectNamespace.sti_name when Namespaces::ProjectNamespace.sti_name
Namespaces::ProjectNamespace Namespaces::ProjectNamespace
when Namespaces::UserNamespace.sti_name when Namespaces::UserNamespace.sti_name
# TODO: We create a normal Namespace until Namespaces::UserNamespace
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68894 is ready
Namespace
else else
Namespace Namespace
end end
......
# frozen_string_literal: true # frozen_string_literal: true
# TODO: currently not created/mapped in the database, will be done in another issue # TODO: currently not created/mapped in the database, will be done in another issue
# https://gitlab.com/gitlab-org/gitlab/-/issues/337102 # https://gitlab.com/gitlab-org/gitlab/-/issues/341070
module Namespaces module Namespaces
class UserNamespace < Namespace class UserNamespace < Namespace
def self.sti_name def self.sti_name
......
...@@ -112,7 +112,9 @@ class User < ApplicationRecord ...@@ -112,7 +112,9 @@ class User < ApplicationRecord
# #
# Namespace for personal projects # Namespace for personal projects
has_one :namespace, -> { where(type: nil) }, dependent: :destroy, foreign_key: :owner_id, inverse_of: :owner, autosave: true # rubocop:disable Cop/ActiveRecordDependent # TODO: change to `type: Namespaces::UserNamespace.sti_name` when
# working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
has_one :namespace, -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) }, dependent: :destroy, foreign_key: :owner_id, inverse_of: :owner, autosave: true # rubocop:disable Cop/ActiveRecordDependent
# Profile # Profile
has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
...@@ -728,7 +730,7 @@ class User < ApplicationRecord ...@@ -728,7 +730,7 @@ class User < ApplicationRecord
end end
def find_by_full_path(path, follow_redirects: false) def find_by_full_path(path, follow_redirects: false)
namespace = Namespace.for_user.find_by_full_path(path, follow_redirects: follow_redirects) namespace = Namespace.user_namespaces.find_by_full_path(path, follow_redirects: follow_redirects)
namespace&.owner namespace&.owner
end end
......
...@@ -452,16 +452,20 @@ module EE ...@@ -452,16 +452,20 @@ module EE
end end
end end
# TODO: change to `type: ::Namespaces::UserNamespace.sti_name` when
# working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
def namespace_union_for_owned(select = :id) def namespace_union_for_owned(select = :id)
::Gitlab::SQL::Union.new([ ::Gitlab::SQL::Union.new([
::Namespace.select(select).where(type: nil, owner: self), ::Namespace.select(select).where(type: [nil, ::Namespaces::UserNamespace.sti_name], owner: self),
owned_groups.select(select).where(parent_id: nil) owned_groups.select(select).where(parent_id: nil)
]).to_sql ]).to_sql
end end
# TODO: change to `type: ::Namespaces::UserNamespace.sti_name` when
# working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
def namespace_union_for_reporter_developer_maintainer_owned(select = :id) def namespace_union_for_reporter_developer_maintainer_owned(select = :id)
::Gitlab::SQL::Union.new([ ::Gitlab::SQL::Union.new([
::Namespace.select(select).where(type: nil, owner: self), ::Namespace.select(select).where(type: [nil, ::Namespaces::UserNamespace.sti_name], owner: self),
reporter_developer_maintainer_owned_groups.select(select).where(parent_id: nil) reporter_developer_maintainer_owned_groups.select(select).where(parent_id: nil)
]).to_sql ]).to_sql
end end
......
...@@ -5,7 +5,9 @@ require 'spec_helper' ...@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe 'Project Insights' do RSpec.describe 'Project Insights' do
it_behaves_like 'Insights page' do it_behaves_like 'Insights page' do
let_it_be(:entity) { create(:project) } let_it_be(:entity) { create(:project) }
let(:route) { url_for([entity.namespace, entity, :insights]) }
let(:path) { project_insights_path(entity) } let(:path) { project_insights_path(entity) }
let(:route) do
project_insights_url(entity)
end
end end
end end
...@@ -1336,12 +1336,20 @@ RSpec.describe User do ...@@ -1336,12 +1336,20 @@ RSpec.describe User do
end end
context 'paid namespaces' do context 'paid namespaces' do
let_it_be(:user) { create(:user) } using RSpec::Parameterized::TableSyntax
let_it_be(:ultimate_group) { create(:group_with_plan, plan: :ultimate_plan) } let_it_be(:ultimate_group) { create(:group_with_plan, plan: :ultimate_plan) }
let_it_be(:bronze_group) { create(:group_with_plan, plan: :bronze_plan) } let_it_be(:bronze_group) { create(:group_with_plan, plan: :bronze_plan) }
let_it_be(:free_group) { create(:group_with_plan, plan: :free_plan) } let_it_be(:free_group) { create(:group_with_plan, plan: :free_plan) }
let_it_be(:group_without_plan) { create(:group) } let_it_be(:group_without_plan) { create(:group) }
# TODO: this `where/when` can be removed in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
# At that point we only need to check `user_namespace`
where(namespace_type: [:namespace, :user_namespace])
with_them do
let(:user) { create(:user, namespace: create(namespace_type)) }
describe '#has_paid_namespace?' do describe '#has_paid_namespace?' do
context 'when the user has Reporter or higher on at least one paid group' do context 'when the user has Reporter or higher on at least one paid group' do
it 'returns true' do it 'returns true' do
...@@ -1400,6 +1408,7 @@ RSpec.describe User do ...@@ -1400,6 +1408,7 @@ RSpec.describe User do
end end
end end
end end
end
describe '#gitlab_employee?' do describe '#gitlab_employee?' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
......
# frozen_string_literal: true
FactoryBot.define do
factory :user_namespace, class: 'Namespaces::UserNamespace', parent: :namespace do
sequence(:name) { |n| "user_namespace#{n}" }
type { Namespaces::UserNamespace.sti_name }
end
end
...@@ -178,7 +178,7 @@ RSpec.describe Namespace do ...@@ -178,7 +178,7 @@ RSpec.describe Namespace do
context 'creating a Group' do context 'creating a Group' do
let(:namespace_type) { group_sti_name } let(:namespace_type) { group_sti_name }
it 'is valid' do it 'is the correct type of namespace' do
expect(namespace).to be_a(Group) expect(namespace).to be_a(Group)
expect(namespace.kind).to eq('group') expect(namespace.kind).to eq('group')
expect(namespace.group_namespace?).to be_truthy expect(namespace.group_namespace?).to be_truthy
...@@ -189,7 +189,7 @@ RSpec.describe Namespace do ...@@ -189,7 +189,7 @@ RSpec.describe Namespace do
let(:namespace_type) { project_sti_name } let(:namespace_type) { project_sti_name }
let(:parent) { create(:group) } let(:parent) { create(:group) }
it 'is valid' do it 'is the correct type of namespace' do
expect(Namespace.find(namespace.id)).to be_a(Namespaces::ProjectNamespace) expect(Namespace.find(namespace.id)).to be_a(Namespaces::ProjectNamespace)
expect(namespace.kind).to eq('project') expect(namespace.kind).to eq('project')
expect(namespace.project_namespace?).to be_truthy expect(namespace.project_namespace?).to be_truthy
...@@ -199,10 +199,8 @@ RSpec.describe Namespace do ...@@ -199,10 +199,8 @@ RSpec.describe Namespace do
context 'creating a UserNamespace' do context 'creating a UserNamespace' do
let(:namespace_type) { user_sti_name } let(:namespace_type) { user_sti_name }
it 'is valid' do it 'is the correct type of namespace' do
# TODO: We create a normal Namespace until expect(Namespace.find(namespace.id)).to be_a(Namespaces::UserNamespace)
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68894 is ready
expect(Namespace.find(namespace.id)).to be_a(Namespace)
expect(namespace.kind).to eq('user') expect(namespace.kind).to eq('user')
expect(namespace.user_namespace?).to be_truthy expect(namespace.user_namespace?).to be_truthy
end end
...@@ -211,7 +209,7 @@ RSpec.describe Namespace do ...@@ -211,7 +209,7 @@ RSpec.describe Namespace do
context 'creating a default Namespace' do context 'creating a default Namespace' do
let(:namespace_type) { nil } let(:namespace_type) { nil }
it 'is valid' do it 'is the correct type of namespace' do
expect(Namespace.find(namespace.id)).to be_a(Namespace) expect(Namespace.find(namespace.id)).to be_a(Namespace)
expect(namespace.kind).to eq('user') expect(namespace.kind).to eq('user')
expect(namespace.user_namespace?).to be_truthy expect(namespace.user_namespace?).to be_truthy
...@@ -221,7 +219,7 @@ RSpec.describe Namespace do ...@@ -221,7 +219,7 @@ RSpec.describe Namespace do
context 'creating an unknown Namespace type' do context 'creating an unknown Namespace type' do
let(:namespace_type) { 'One' } let(:namespace_type) { 'One' }
it 'defaults to a Namespace' do it 'creates a default Namespace' do
expect(Namespace.find(namespace.id)).to be_a(Namespace) expect(Namespace.find(namespace.id)).to be_a(Namespace)
expect(namespace.kind).to eq('user') expect(namespace.kind).to eq('user')
expect(namespace.user_namespace?).to be_truthy expect(namespace.user_namespace?).to be_truthy
......
# frozen_string_literal: true
require 'spec_helper'
# Main user namespace functionality it still in `Namespace`, so most
# of the specs are in `namespace_spec.rb`.
# UserNamespace specific specs will end up being migrated here.
RSpec.describe Namespaces::UserNamespace, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:owner) }
end
end
...@@ -2542,7 +2542,14 @@ RSpec.describe User do ...@@ -2542,7 +2542,14 @@ RSpec.describe User do
end end
describe '.find_by_full_path' do describe '.find_by_full_path' do
let!(:user) { create(:user) } using RSpec::Parameterized::TableSyntax
# TODO: this `where/when` can be removed in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
# At that point we only need to check `user_namespace`
where(namespace_type: [:namespace, :user_namespace])
with_them do
let!(:user) { create(:user, namespace: create(namespace_type)) }
context 'with a route matching the given path' do context 'with a route matching the given path' do
let!(:route) { user.namespace.route } let!(:route) { user.namespace.route }
...@@ -2611,6 +2618,7 @@ RSpec.describe User do ...@@ -2611,6 +2618,7 @@ RSpec.describe User do
end end
end end
end end
end
describe 'all_ssh_keys' do describe 'all_ssh_keys' do
it { is_expected.to have_many(:keys).dependent(:destroy) } it { is_expected.to have_many(:keys).dependent(:destroy) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment