Commit 4577f7af authored by Alex Kalderimis's avatar Alex Kalderimis

Ensure HasWiki constructs wikis with users as owners

This adds a concept of `default_actor` that `HasWiki` instances must
implement. This is implemented differently for projects and groups.
The contract is that `default_actor` must return a User with ownership
privileges over the object.

Wiki Owner differs from Owner of these models as wiki_owner must have
the type `User`, but `Project#owner` can be a `Group` for instance.
Groups can have many owners, so we select the first one, before
ascending the chain of parent groups.

This is vital since otherwise `HasWiki#wiki` will return wikis that
cannot save their own pages.
parent c2973104
......@@ -17,7 +17,7 @@ module HasWiki
def wiki
strong_memoize(:wiki) do
Wiki.for_container(self, self.owner)
Wiki.for_container(self, self.default_owner)
end
end
......
......@@ -563,6 +563,10 @@ class Group < Namespace
all_projects.update_all(shared_runners_enabled: false)
end
def default_owner
owners.first || parent&.default_owner || owner
end
private
def update_two_factor_requirement
......
......@@ -1395,6 +1395,16 @@ class Project < ApplicationRecord
group || namespace.try(:owner)
end
def default_owner
obj = owner
if obj.respond_to?(:default_owner)
obj.default_owner
else
obj
end
end
def to_ability_name
model_name.singular
end
......
......@@ -35,6 +35,7 @@ class Wiki
def initialize(container, user = nil)
@container = container
@user = user
raise ArgumentError, "user must be a User, got #{user.class}" if user && !user.is_a?(User)
end
def path
......
......@@ -1541,4 +1541,48 @@ RSpec.describe Group do
end
end
end
describe '#default_owner' do
let(:group) { build(:group) }
context 'the group has owners' do
before do
group.add_owner(create(:user))
group.add_owner(create(:user))
end
it 'is the first owner' do
expect(group.default_owner)
.to eq(group.owners.first)
.and be_a(User)
end
end
context 'the group has a parent' do
let(:parent) { build(:group) }
before do
group.parent = parent
parent.add_owner(create(:user))
end
it 'is the first owner of the parent' do
expect(group.default_owner)
.to eq(parent.default_owner)
.and be_a(User)
end
end
context 'we fallback to group.owner' do
before do
group.owner = build(:user)
end
it 'is the group.owner' do
expect(group.default_owner)
.to eq(group.owner)
.and be_a(User)
end
end
end
end
......@@ -1084,6 +1084,30 @@ RSpec.describe Project do
end
end
describe '#default_owner' do
let_it_be(:owner) { create(:user) }
let_it_be(:namespace) { create(:namespace, owner: owner) }
context 'the project does not have a group' do
let(:project) { build(:project, namespace: namespace) }
it 'is the namespace owner' do
expect(project.default_owner).to eq(owner)
end
end
context 'the project is in a group' do
let(:group) { build(:group) }
let(:project) { build(:project, group: group, namespace: namespace) }
it 'is the group owner' do
allow(group).to receive(:default_owner).and_return(Object.new)
expect(project.default_owner).to eq(group.default_owner)
end
end
end
describe '#external_wiki' do
let(:project) { create(:project) }
......
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