diff --git a/docs/api/apiv3/components/schemas/wiki_provider_read_model.yml b/docs/api/apiv3/components/schemas/wiki_provider_read_model.yml new file mode 100644 index 000000000000..d00aa6332e8f --- /dev/null +++ b/docs/api/apiv3/components/schemas/wiki_provider_read_model.yml @@ -0,0 +1,66 @@ +# Schema: StatusModel +--- +type: object +required: + - _type + - _links + - id + - name + - enabled + - createdAt + - updatedAt +additionalProperties: false +properties: + _type: + type: string + enum: + - WikiProvider + id: + type: integer + description: ID of this wiki provider + minimum: 1 + name: + type: string + description: The name given to the provider. This will be shown in most user interfaces. + enabled: + type: boolean + description: Whether the provider is enabled and usable. Only settable for the internal provider. + universalIdentifier: + type: string + description: | + The universal identifier of the remote wiki provider. Can be used to disambiguate between multiple wiki providers, e.g. when filtering page links. + + **Only visible to admins**, because this is a configuration-only property. + createdAt: + type: string + format: date-time + description: The time at which the provider was first set-up in OpenProject. + updatedAt: + type: string + format: date-time + description: The time at which the provider setup was last changed. + _links: + type: object + required: + - self + additionalProperties: false + properties: + self: + allOf: + - $ref: './link.yml' + - description: |- + This wiki provider. + + **Resource**: WikiProvider +example: + _type: WikiProvider + id: 1 + name: Internal wiki + enabled: true + universalIdentifier: internal + createdAt: '2026-03-26T08:27:59.078Z' + updatedAt: '2026-03-26T08:27:59.078Z' + _links: + self: + href: "/api/v3/wiki_providers/1" + title: Internal wiki diff --git a/lib/api/v3/utilities/endpoints/index.rb b/lib/api/v3/utilities/endpoints/index.rb index 2df67f3e157c..fbb724c380db 100644 --- a/lib/api/v3/utilities/endpoints/index.rb +++ b/lib/api/v3/utilities/endpoints/index.rb @@ -35,9 +35,11 @@ def initialize(model:, api_name: model.name.demodulize, scope: nil, render_representer: nil, - self_path: api_name.underscore.pluralize) + self_path: api_name.underscore.pluralize, + query_class: nil) super(model:, api_name:, scope:, render_representer:) + @query_class = query_class self.self_path = self_path end @@ -53,7 +55,7 @@ def mount def parse(request) ParamsToQueryService - .new(model, request.current_user) + .new(model, request.current_user, query_class: @query_class) .call(request.params) end diff --git a/modules/wikis/app/models/wikis/queries/provider_query.rb b/modules/wikis/app/models/wikis/queries/provider_query.rb new file mode 100644 index 000000000000..dc5f61d8c094 --- /dev/null +++ b/modules/wikis/app/models/wikis/queries/provider_query.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module Wikis::Queries + class ProviderQuery + include Queries::BaseQuery + include Queries::UnpersistedQuery + + class << self + def model + @model ||= ::Wikis::Provider + end + end + end +end diff --git a/modules/wikis/lib/api/v3/wikis/provider_collection_representer.rb b/modules/wikis/lib/api/v3/wikis/provider_collection_representer.rb new file mode 100644 index 000000000000..dfcdbd022890 --- /dev/null +++ b/modules/wikis/lib/api/v3/wikis/provider_collection_representer.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module API + module V3 + module Wikis + class ProviderCollectionRepresenter < ::API::Decorators::UnpaginatedCollection + end + end + end +end diff --git a/modules/wikis/lib/api/v3/wikis/provider_representer.rb b/modules/wikis/lib/api/v3/wikis/provider_representer.rb new file mode 100644 index 000000000000..a64407e40c70 --- /dev/null +++ b/modules/wikis/lib/api/v3/wikis/provider_representer.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module API::V3::Wikis + class ProviderRepresenter < ::API::Decorators::Single + include API::Decorators::LinkedResource + include API::Decorators::DateProperty + + property :id + property :name + property :enabled + property :universal_identifier, + exec_context: :decorator, + getter: ->(*) { represented.universal_identifier }, + skip_render: ->(*) { !current_user.admin? } + date_time_property :created_at + date_time_property :updated_at + + self_link + + def _type + "WikiProvider" + end + end +end diff --git a/modules/wikis/lib/api/v3/wikis/providers_api.rb b/modules/wikis/lib/api/v3/wikis/providers_api.rb new file mode 100644 index 000000000000..ad5281d7daf7 --- /dev/null +++ b/modules/wikis/lib/api/v3/wikis/providers_api.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +class API::V3::Wikis::ProvidersAPI < API::OpenProjectAPI + # TODO: Authorization... Which permissions are needed to enumerate wiki providers? + resources :wiki_providers do + get &API::V3::Utilities::Endpoints::Index.new( + model: ::Wikis::Provider, + scope: -> { ::Wikis::Provider.all }, + self_path: :wiki_providers, + render_representer: API::V3::Wikis::ProviderCollectionRepresenter, + query_class: Wikis::Queries::ProviderQuery + ).mount + + route_param :provider_id, type: Integer, desc: "Wiki id" do + get &API::V3::Utilities::Endpoints::Show.new( + model: ::Wikis::Provider, + render_representer: API::V3::Wikis::ProviderRepresenter + ).mount + end + end +end diff --git a/modules/wikis/lib/open_project/wikis/engine.rb b/modules/wikis/lib/open_project/wikis/engine.rb index 2b6748612b49..03e1d2b884ea 100644 --- a/modules/wikis/lib/open_project/wikis/engine.rb +++ b/modules/wikis/lib/open_project/wikis/engine.rb @@ -67,5 +67,17 @@ class Engine < ::Rails::Engine end replace_principal_references "Wikis::PageLink" => %i[author_id] + + add_api_path :wiki_providers do + "#{root}/wiki_providers" + end + + add_api_path :wiki_provider do |id| + "#{wiki_providers}/#{id}" + end + + add_api_endpoint "API::V3::Root" do + mount ::API::V3::Wikis::ProvidersAPI + end end end diff --git a/modules/wikis/spec/lib/api/v3/wikis/provider_representer_spec.rb b/modules/wikis/spec/lib/api/v3/wikis/provider_representer_spec.rb new file mode 100644 index 000000000000..1978ebb93e0f --- /dev/null +++ b/modules/wikis/spec/lib/api/v3/wikis/provider_representer_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" + +RSpec.describe API::V3::Wikis::ProviderRepresenter do + include API::V3::Utilities::PathHelper + + describe "rendering" do + subject(:generated) { representer.to_json } + + let(:representer) { described_class.create(provider, current_user:) } + let(:current_user) { build_stubbed(:user) } + + shared_examples_for "hides configuration properties from non-admins" do + context "as an admin user" do + let(:current_user) { build_stubbed(:admin) } + + it "shows the universalIdentifier" do + expect(generated).to be_json_eql(provider.universal_identifier.to_json).at_path("universalIdentifier") + end + end + + context "as a non-admin user" do + it "hides the universalIdentifier"do + expect(generated).not_to have_json_path("universalIdentifier") + end + end + end + + context "for internal wiki provider" do + let(:provider) { create(:internal_wiki_provider) } + + it "fulfills the documented schema" do + expect(generated).to match_json_schema.from_docs("wiki_provider_read_model") + end + + it_behaves_like "hides configuration properties from non-admins" + end + + context "for XWiki provider" do + let(:provider) { create(:xwiki_provider) } + + it "fulfills the documented schema" do + expect(generated).to match_json_schema.from_docs("wiki_provider_read_model") + end + + it_behaves_like "hides configuration properties from non-admins" + end + end +end