Commit eb268b49 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '207867-wikipage-services' into 'master'

Allow WikiPages services to accept group

See merge request gitlab-org/gitlab!31169
parents 4f11ffba f41db880
......@@ -65,7 +65,7 @@ class Projects::WikisController < Projects::ApplicationController
def update
return render('empty') unless can?(current_user, :create_wiki, @project)
@page = WikiPages::UpdateService.new(@project, current_user, wiki_params).execute(@page)
@page = WikiPages::UpdateService.new(container: @project, current_user: current_user, params: wiki_params).execute(@page)
if @page.valid?
redirect_to(
......@@ -81,7 +81,7 @@ class Projects::WikisController < Projects::ApplicationController
end
def create
@page = WikiPages::CreateService.new(@project, current_user, wiki_params).execute
@page = WikiPages::CreateService.new(container: @project, current_user: current_user, params: wiki_params).execute
if @page.persisted?
redirect_to(
......@@ -112,7 +112,7 @@ class Projects::WikisController < Projects::ApplicationController
end
def destroy
WikiPages::DestroyService.new(@project, current_user).execute(@page)
WikiPages::DestroyService.new(container: @project, current_user: current_user).execute(@page)
redirect_to project_wiki_path(@project, :home),
status: :found,
......
......@@ -483,6 +483,16 @@ class Group < Namespace
false
end
def execute_hooks(data, hooks_scope)
# NOOP
# TODO: group hooks https://gitlab.com/gitlab-org/gitlab/-/issues/216904
end
def execute_services(data, hooks_scope)
# NOOP
# TODO: group hooks https://gitlab.com/gitlab-org/gitlab/-/issues/216904
end
private
def update_two_factor_requirement
......
......@@ -6,13 +6,13 @@ module WikiPages
# - external_action: the action we report to external clients with webhooks
# - usage_counter_action: the action that we count in out internal counters
# - event_action: what we record as the value of `Event#action`
class BaseService < ::BaseService
class BaseService < ::BaseContainerService
private
def execute_hooks(page)
page_data = payload(page)
@project.execute_hooks(page_data, :wiki_page_hooks)
@project.execute_services(page_data, :wiki_page_hooks)
container.execute_hooks(page_data, :wiki_page_hooks)
container.execute_services(page_data, :wiki_page_hooks)
increment_usage
create_wiki_event(page)
end
......
......@@ -3,8 +3,8 @@
module WikiPages
class CreateService < WikiPages::BaseService
def execute
project_wiki = ProjectWiki.new(@project, current_user)
page = WikiPage.new(project_wiki)
wiki = Wiki.for_container(container, current_user)
page = WikiPage.new(wiki)
if page.create(@params)
execute_hooks(page)
......
......@@ -16,9 +16,18 @@ module EE
process_wiki_repository_update
end
def create_wiki_event(_page)
# TODO: group hooks https://gitlab.com/gitlab-org/gitlab/-/issues/216904
return if container.is_a?(Group)
super
end
def process_wiki_repository_update
if ::Gitlab::Geo.primary?
::Geo::RepositoryUpdatedService.new(project.wiki.repository).execute
# TODO: Geo support for group wiki
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
if ::Gitlab::Geo.primary? && container.is_a?(Project)
::Geo::RepositoryUpdatedService.new(container.wiki.repository).execute
end
end
end
......
......@@ -3,7 +3,6 @@
require 'spec_helper'
describe WikiPages::CreateService do
let(:project) { create(:project, :wiki_repo) }
let(:user) { create(:user) }
let(:opts) do
......@@ -14,18 +13,16 @@ describe WikiPages::CreateService do
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_maintainer(user)
end
subject(:service) { described_class.new(container: container, current_user: user, params: opts) }
describe '#execute' do
let(:container) { create(:project, :wiki_repo) }
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true }
repository_updated_service = instance_double('::Geo::RepositoryUpdatedService')
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(project.wiki.repository) { repository_updated_service }
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(container.wiki.repository) { repository_updated_service }
expect(repository_updated_service).to receive(:execute)
service.execute
......@@ -34,7 +31,19 @@ describe WikiPages::CreateService do
it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new).with(project.wiki.repository)
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute
end
end
it_behaves_like 'WikiPages::CreateService#execute', :group do
# TODO: Geo support for group wiki
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
it 'does not call Geo::RepositoryUpdatedService when container is group' do
allow(Gitlab::Geo).to receive(:primary?) { true }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute
end
......
......@@ -3,22 +3,19 @@
require 'spec_helper'
describe WikiPages::DestroyService do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
subject(:service) { described_class.new(project, user) }
before do
project.add_maintainer(user)
end
subject(:service) { described_class.new(container: container, current_user: user) }
describe '#execute' do
let(:container) { create(:project) }
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true }
repository_updated_service = instance_double('::Geo::RepositoryUpdatedService')
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(project.wiki.repository) { repository_updated_service }
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(container.wiki.repository) { repository_updated_service }
expect(repository_updated_service).to receive(:execute)
service.execute(page)
......@@ -27,7 +24,19 @@ describe WikiPages::DestroyService do
it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new).with(project.wiki.repository)
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute(page)
end
end
it_behaves_like 'WikiPages::DestroyService#execute', :group do
# TODO: Geo support for group wiki
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
it 'does not call Geo::RepositoryUpdatedService when container is group' do
allow(Gitlab::Geo).to receive(:primary?) { true }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute(page)
end
......
......@@ -3,7 +3,6 @@
require 'spec_helper'
describe WikiPages::UpdateService do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
......@@ -15,18 +14,16 @@ describe WikiPages::UpdateService do
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_maintainer(user)
end
subject(:service) { described_class.new(container: container, current_user: user, params: opts) }
describe '#execute' do
let(:container) { create(:project) }
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true }
repository_updated_service = instance_double('::Geo::RepositoryUpdatedService')
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(project.wiki.repository) { repository_updated_service }
expect(::Geo::RepositoryUpdatedService).to receive(:new).with(container.wiki.repository) { repository_updated_service }
expect(repository_updated_service).to receive(:execute)
service.execute(page)
......@@ -35,7 +32,19 @@ describe WikiPages::UpdateService do
it 'does not call Geo::RepositoryUpdatedService when not running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { false }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new).with(project.wiki.repository)
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute(page)
end
end
it_behaves_like 'WikiPages::UpdateService#execute', :group do
# TODO: Geo support for group wiki
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
it 'does not call Geo::RepositoryUpdatedService when container is group' do
allow(Gitlab::Geo).to receive(:primary?) { true }
expect(::Geo::RepositoryUpdatedService).not_to receive(:new)
service.execute(page)
end
......
......@@ -70,7 +70,7 @@ module API
post ':id/wikis' do
authorize! :create_wiki, user_project
page = WikiPages::CreateService.new(user_project, current_user, params).execute
page = WikiPages::CreateService.new(container: user_project, current_user: current_user, params: params).execute
if page.valid?
present page, with: Entities::WikiPage
......@@ -91,7 +91,7 @@ module API
put ':id/wikis/:slug' do
authorize! :create_wiki, user_project
page = WikiPages::UpdateService.new(user_project, current_user, params).execute(wiki_page)
page = WikiPages::UpdateService.new(container: user_project, current_user: current_user, params: params).execute(wiki_page)
if page.valid?
present page, with: Entities::WikiPage
......@@ -107,7 +107,7 @@ module API
delete ':id/wikis/:slug' do
authorize! :admin_wiki, user_project
WikiPages::DestroyService.new(user_project, current_user).execute(wiki_page)
WikiPages::DestroyService.new(container: user_project, current_user: current_user).execute(wiki_page)
no_content!
end
......
......@@ -8,6 +8,9 @@ module Gitlab
def build(wiki_page, user, action)
wiki = wiki_page.wiki
# TODO: group hooks https://gitlab.com/gitlab-org/gitlab/-/issues/216904
return {} if wiki.container.is_a?(Group)
{
object_kind: wiki_page.class.name.underscore,
user: user.hook_attrs,
......
......@@ -10,7 +10,7 @@ describe WikiPages::BaseService do
counter = Gitlab::UsageDataCounters::WikiPageCounter
error = counter::UnknownEvent
let(:subject) { bad_service_class.new(project, user, {}) }
let(:subject) { bad_service_class.new(container: project, current_user: user) }
context 'the class implements usage_counter_action incorrectly' do
let(:bad_service_class) do
......
......@@ -3,96 +3,5 @@
require 'spec_helper'
describe WikiPages::CreateService do
let(:project) { create(:project, :wiki_repo) }
let(:user) { create(:user) }
let(:page_title) { 'Title' }
let(:opts) do
{
title: page_title,
content: 'Content for wiki page',
format: 'markdown'
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_developer(user)
end
describe '#execute' do
it 'creates wiki page with valid attributes' do
page = service.execute
expect(page).to be_valid
expect(page.title).to eq(opts[:title])
expect(page.content).to eq(opts[:content])
expect(page.format).to eq(opts[:format].to_sym)
end
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute
end
it 'counts wiki page creation' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.to change { counter.read(:create) }.by 1
end
shared_examples 'correct event created' do
it 'creates appropriate events' do
expect { service.execute }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::CREATED,
target: have_attributes(canonical_slug: page_title)
)
end
end
context 'the new page is at the top level' do
let(:page_title) { 'root-level-page' }
include_examples 'correct event created'
end
context 'the new page is in a subsection' do
let(:page_title) { 'subsection/page' }
include_examples 'correct event created'
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute }.not_to change(Event, :count)
end
end
context 'when the options are bad' do
let(:page_title) { '' }
it 'does not count a creation event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.not_to change { counter.read(:create) }
end
it 'does not record the activity' do
expect { service.execute }.not_to change(Event, :count)
end
it 'reports the error' do
expect(service.execute).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
it_behaves_like 'WikiPages::CreateService#execute', :project
end
......@@ -3,52 +3,5 @@
require 'spec_helper'
describe WikiPages::DestroyService do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
subject(:service) { described_class.new(project, user) }
before do
project.add_developer(user)
end
describe '#execute' do
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(page)
service.execute(page)
end
it 'increments the delete count' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(page) }.to change { counter.read(:delete) }.by 1
end
it 'creates a new wiki page deletion event' do
expect { service.execute(page) }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::DESTROYED,
target: have_attributes(canonical_slug: page.slug)
)
end
it 'does not increment the delete count if the deletion failed' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(nil) }.not_to change { counter.read(:delete) }
end
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute(page) }.not_to change(Event, :count)
end
end
it_behaves_like 'WikiPages::DestroyService#execute', :project
end
......@@ -3,100 +3,5 @@
require 'spec_helper'
describe WikiPages::UpdateService do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
let(:page_title) { 'New Title' }
let(:opts) do
{
content: 'New content for wiki page',
format: 'markdown',
message: 'New wiki message',
title: page_title
}
end
subject(:service) { described_class.new(project, user, opts) }
before do
project.add_developer(user)
end
describe '#execute' do
it 'updates the wiki page' do
updated_page = service.execute(page)
expect(updated_page).to be_valid
expect(updated_page.message).to eq(opts[:message])
expect(updated_page.content).to eq(opts[:content])
expect(updated_page.format).to eq(opts[:format].to_sym)
expect(updated_page.title).to eq(page_title)
end
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute(page)
end
it 'counts edit events' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.to change { counter.read(:update) }.by 1
end
shared_examples 'adds activity event' do
it 'adds a new wiki page activity event' do
expect { service.execute(page) }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::UPDATED,
wiki_page: page,
target_title: page.title
)
end
end
context 'the page is at the top level' do
let(:page_title) { 'Top level page' }
include_examples 'adds activity event'
end
context 'the page is in a subsection' do
let(:page_title) { 'Subsection / secondary page' }
include_examples 'adds activity event'
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute(page) }.not_to change(Event, :count)
end
end
context 'when the options are bad' do
let(:page_title) { '' }
it 'does not count an edit event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.not_to change { counter.read(:update) }
end
it 'does not record the activity' do
expect { service.execute page }.not_to change(Event, :count)
end
it 'reports the error' do
expect(service.execute(page)).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
it_behaves_like 'WikiPages::UpdateService#execute', :project
end
# frozen_string_literal: true
RSpec.shared_examples 'WikiPages::CreateService#execute' do |container_type|
let(:container) { create(container_type, :wiki_repo) }
let(:user) { create(:user) }
let(:page_title) { 'Title' }
let(:opts) do
{
title: page_title,
content: 'Content for wiki page',
format: 'markdown'
}
end
subject(:service) { described_class.new(container: container, current_user: user, params: opts) }
it 'creates wiki page with valid attributes' do
page = service.execute
expect(page).to be_valid
expect(page).to be_persisted
expect(page.title).to eq(opts[:title])
expect(page.content).to eq(opts[:content])
expect(page.format).to eq(opts[:format].to_sym)
end
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute
end
it 'counts wiki page creation' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.to change { counter.read(:create) }.by 1
end
shared_examples 'correct event created' do
it 'creates appropriate events' do
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904
pending('group wiki support') if container_type == :group
expect { service.execute }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::CREATED,
target: have_attributes(canonical_slug: page_title)
)
end
end
context 'the new page is at the top level' do
let(:page_title) { 'root-level-page' }
include_examples 'correct event created'
end
context 'the new page is in a subsection' do
let(:page_title) { 'subsection/page' }
include_examples 'correct event created'
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute }.not_to change(Event, :count)
end
end
context 'when the options are bad' do
let(:page_title) { '' }
it 'does not count a creation event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute }.not_to change { counter.read(:create) }
end
it 'does not record the activity' do
expect { service.execute }.not_to change(Event, :count)
end
it 'reports the error' do
expect(service.execute).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
# frozen_string_literal: true
RSpec.shared_examples 'WikiPages::DestroyService#execute' do |container_type|
let(:container) { create(container_type) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
subject(:service) { described_class.new(container: container, current_user: user) }
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(page)
service.execute(page)
end
it 'increments the delete count' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(page) }.to change { counter.read(:delete) }.by 1
end
it 'creates a new wiki page deletion event' do
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904
pending('group wiki support') if container_type == :group
expect { service.execute(page) }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::DESTROYED,
target: have_attributes(canonical_slug: page.slug)
)
end
it 'does not increment the delete count if the deletion failed' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute(nil) }.not_to change { counter.read(:delete) }
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute(page) }.not_to change(Event, :count)
end
end
end
# frozen_string_literal: true
RSpec.shared_examples 'WikiPages::UpdateService#execute' do |container_type|
let(:container) { create(container_type, :wiki_repo) }
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
let(:page_title) { 'New Title' }
let(:opts) do
{
content: 'New content for wiki page',
format: 'markdown',
message: 'New wiki message',
title: page_title
}
end
subject(:service) { described_class.new(container: container, current_user: user, params: opts) }
it 'updates the wiki page' do
updated_page = service.execute(page)
expect(updated_page).to be_valid
expect(updated_page.message).to eq(opts[:message])
expect(updated_page.content).to eq(opts[:content])
expect(updated_page.format).to eq(opts[:format].to_sym)
expect(updated_page.title).to eq(page_title)
end
it 'executes webhooks' do
expect(service).to receive(:execute_hooks).once.with(WikiPage)
service.execute(page)
end
it 'counts edit events' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.to change { counter.read(:update) }.by 1
end
shared_examples 'adds activity event' do
it 'adds a new wiki page activity event' do
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904
pending('group wiki support') if container_type == :group
expect { service.execute(page) }.to change { Event.count }.by 1
expect(Event.recent.first).to have_attributes(
action: Event::UPDATED,
wiki_page: page,
target_title: page.title
)
end
end
context 'the page is at the top level' do
let(:page_title) { 'Top level page' }
include_examples 'adds activity event'
end
context 'the page is in a subsection' do
let(:page_title) { 'Subsection / secondary page' }
include_examples 'adds activity event'
end
context 'the feature is disabled' do
before do
stub_feature_flags(wiki_events: false)
end
it 'does not record the activity' do
expect { service.execute(page) }.not_to change(Event, :count)
end
end
context 'when the options are bad' do
let(:page_title) { '' }
it 'does not count an edit event' do
counter = Gitlab::UsageDataCounters::WikiPageCounter
expect { service.execute page }.not_to change { counter.read(:update) }
end
it 'does not record the activity' do
expect { service.execute page }.not_to change(Event, :count)
end
it 'reports the error' do
expect(service.execute(page)).to be_invalid
.and have_attributes(errors: be_present)
end
end
end
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