mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
[75226] Update XWiki auth integration (#23321)
Update the XWiki auth screen: added client secret, aligned the UI with the storage UI. Auth now supports only registered clients on the XWiki side. --------- Co-authored-by: Jan Sandbrink <j.sandbrink@openproject.com>
This commit is contained in:
@@ -36,11 +36,9 @@ module OAuthClients
|
||||
validates :client_id, presence: true, length: { maximum: 255 }
|
||||
|
||||
attribute :client_secret, writable: true
|
||||
validates :client_secret, presence: true, if: :client_secret_required?
|
||||
validates :client_secret, presence: true
|
||||
validates :client_secret, length: { maximum: 255 }
|
||||
|
||||
def client_secret_required? = true
|
||||
|
||||
attribute :integration_type, writable: true
|
||||
validates :integration_type, presence: true
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
component_wrapper do
|
||||
flex_layout(mb: 3) do |general_info_row|
|
||||
general_info_row.with_row do
|
||||
render(Primer::Beta::Text.new(font_weight: :bold)) { t("wikis.admin.wiki_providers.xwiki_instance") }
|
||||
render(Primer::Beta::Text.new(font_weight: :bold)) { t("wikis.provider_types.#{wiki_provider}.name") }
|
||||
end
|
||||
|
||||
general_info_row.with_row do
|
||||
render(Primer::Beta::Text.new(color: :subtle, test_selector: "wiki-provider-configuration-instructions")) do
|
||||
t(".xwiki_instance_description")
|
||||
t(".provider_description")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+7
-5
@@ -1,12 +1,14 @@
|
||||
<%=
|
||||
component_wrapper do
|
||||
flex_layout(flex_items: :center) do |credentials_row|
|
||||
credentials_row.with_row do
|
||||
render(Primer::Beta::Text.new(font_weight: :bold)) { t("wikis.admin.wiki_providers.oauth.openproject_oauth") }
|
||||
end
|
||||
|
||||
credentials_row.with_row(mb: 3) do
|
||||
render(Primer::Beta::Text.new(color: :subtle)) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.openproject_oauth_description") }
|
||||
render(Primer::Alpha::Banner.new(icon: :alert, scheme: :warning)) do
|
||||
helpers.link_translate(
|
||||
"wikis.instructions.xwiki.oauth_application_details_html",
|
||||
links: { xwiki_admin_link: xwiki_admin_url },
|
||||
external: true
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
credentials_row.with_row(mb: 3) do
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
module Wikis::Admin::Forms
|
||||
class OAuthApplicationFormComponent < Wikis::Admin::WikiProviderComponent
|
||||
OPENPROJECT_PLUGIN_ADMIN_PATH = "/bin/admin/XWiki/XWikiPreferences?editor=globaladmin§ion=OpenProject"
|
||||
|
||||
def self.wrapper_key = :wiki_provider_oauth_application_section
|
||||
|
||||
delegate :oauth_application, to: :wiki_provider
|
||||
@@ -43,5 +45,9 @@ module Wikis::Admin::Forms
|
||||
url_helpers.edit_admin_settings_wiki_provider_path(wiki_provider)
|
||||
end
|
||||
end
|
||||
|
||||
def xwiki_admin_url
|
||||
"#{wiki_provider.url.to_s.chomp('/')}#{OPENPROJECT_PLUGIN_ADMIN_PATH}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+29
-5
@@ -14,19 +14,43 @@
|
||||
render(Primer::Beta::Text.new(color: :subtle)) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.provider_oauth_description") }
|
||||
end
|
||||
|
||||
oauth_client_row.with_row(mb: 3) do
|
||||
render(Primer::Alpha::TextField.new(
|
||||
name: "oauth_client[client_id]",
|
||||
label: t(".client_id"),
|
||||
visually_hide_label: false,
|
||||
value: resolved_oauth_client.client_id,
|
||||
input_width: :large,
|
||||
required: true,
|
||||
validation_message: validation_message_for(:client_id)
|
||||
))
|
||||
end
|
||||
|
||||
oauth_client_row.with_row(mb: 3) do
|
||||
render(Primer::Alpha::TextField.new(
|
||||
name: "oauth_client[client_secret]",
|
||||
label: t(".client_secret"),
|
||||
visually_hide_label: false,
|
||||
value: resolved_oauth_client.client_secret,
|
||||
input_width: :large,
|
||||
required: true,
|
||||
validation_message: validation_message_for(:client_secret)
|
||||
))
|
||||
end
|
||||
|
||||
oauth_client_row.with_row(mb: 3) do
|
||||
render(Primer::OpenProject::InputGroup.new(input_width: :large)) do |input_group|
|
||||
input_group.with_text_input(
|
||||
name: "oauth_client[client_id]",
|
||||
label: t(".client_id"),
|
||||
name: "oauth_client[redirect_uri]",
|
||||
label: t(".redirect_uri"),
|
||||
visually_hide_label: false,
|
||||
value: resolved_oauth_client.client_id,
|
||||
readonly: true
|
||||
value: resolved_oauth_client.redirect_uri
|
||||
)
|
||||
input_group.with_trailing_action_clipboard_copy_button(
|
||||
value: resolved_oauth_client.client_id,
|
||||
value: resolved_oauth_client.redirect_uri,
|
||||
aria: { label: t("button_copy_to_clipboard") }
|
||||
)
|
||||
input_group.with_caption { t(".redirect_uri_caption") }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -51,7 +51,14 @@ module Wikis::Admin::Forms
|
||||
def resolved_oauth_client
|
||||
oauth_client ||
|
||||
wiki_provider.oauth_client ||
|
||||
wiki_provider.build_oauth_client(client_id: Wikis::XWikiProvider.generate_client_id)
|
||||
wiki_provider.build_oauth_client(
|
||||
client_id: Wikis::XWikiProvider.generate_client_id,
|
||||
client_secret: Wikis::XWikiProvider.generate_client_secret
|
||||
)
|
||||
end
|
||||
|
||||
def validation_message_for(attribute)
|
||||
resolved_oauth_client.errors.messages_for(attribute).to_sentence.presence
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
component_wrapper do
|
||||
grid_layout("op-storage-view--row", tag: :div, align_items: :center) do |grid|
|
||||
grid.with_area(:item, tag: :div, mr: 3) do
|
||||
concat(render(Primer::Beta::Text.new(font_weight: :bold, mr: 1)) { t("wikis.admin.wiki_providers.xwiki_instance") })
|
||||
concat(render(Primer::Beta::Text.new(font_weight: :bold, mr: 1)) { t("wikis.provider_types.#{wiki_provider}.name") })
|
||||
concat(render(Primer::Beta::Label.new(scheme: :success, test_selector: "wiki-provider-general-info-status")) { t(:label_completed) })
|
||||
end
|
||||
|
||||
grid.with_area(:description, tag: :div, color: :subtle, test_selector: "wiki-provider-description") do
|
||||
concat(render(Primer::Beta::Text.new) { "#{wiki_provider.name} - " })
|
||||
concat(render(Primer::Beta::Link.new(href: wiki_provider.url, target: "_blank", underline: true)) { wiki_provider.url })
|
||||
concat(render(Primer::Beta::Text.new) { "#{t("wikis.provider_types.#{wiki_provider}.name")} - #{wiki_provider.name} - #{wiki_provider.url}" })
|
||||
if wiki_provider.url.present?
|
||||
concat(render(Primer::Beta::Text.new) { " - " })
|
||||
concat(helpers.static_link_to(href: wiki_provider.url, label: t("wikis.buttons.open_wiki"), underline: true))
|
||||
end
|
||||
end
|
||||
|
||||
grid.with_area(:"icon-button", tag: :div, color: :muted) do
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
end
|
||||
|
||||
grid.with_area(:description, tag: :div, color: :subtle) do
|
||||
render(Primer::Beta::Text.new) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.openproject_oauth_description") }
|
||||
if oauth_application.present?
|
||||
render(Primer::Beta::Text.new) { "#{t(".label_oauth_client_id")}: #{oauth_application.uid}" }
|
||||
else
|
||||
render(Primer::Beta::Text.new) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.openproject_oauth_description") }
|
||||
end
|
||||
end
|
||||
|
||||
if wiki_provider.persisted?
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
end
|
||||
end
|
||||
|
||||
grid.with_area(:description, tag: :div, color: :subtle) do
|
||||
render(Primer::Beta::Text.new) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.provider_oauth_description") }
|
||||
grid.with_area(:description, classes: "wb-break-word", tag: :div, color: :subtle) do
|
||||
if oauth_client.present?
|
||||
render(Primer::Beta::Text.new) { "#{t('.label_oauth_client_id')}: #{oauth_client.client_id}" }
|
||||
else
|
||||
render(Primer::Beta::Text.new) { t("wikis.admin.wiki_providers.#{wiki_provider}.oauth.provider_oauth_description") }
|
||||
end
|
||||
end
|
||||
|
||||
if wiki_provider.persisted?
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
end
|
||||
|
||||
grid.with_area(:provider, tag: :div, color: :subtle, mr: 3, hide: :sm) do
|
||||
render(Primer::Beta::Text.new(color: :subtle)) { wiki_provider.model_name.human }
|
||||
render(Primer::Beta::Text.new(color: :subtle)) { t("wikis.provider_types.#{wiki_provider}.name") }
|
||||
end
|
||||
|
||||
grid.with_area(:time, tag: :div, color: :subtle, hide: :sm) do
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# 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
|
||||
module OAuthClients
|
||||
# XWiki uses a public OAuth client (RFC 6749 §2.1) — no client_secret is issued.
|
||||
class XWikiCreateContract < ::OAuthClients::CreateContract
|
||||
def client_secret_required? = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -42,7 +42,10 @@ module Wikis
|
||||
menu_item :wiki_providers
|
||||
|
||||
def new
|
||||
oauth_client = OAuthClient.new(client_id: Wikis::XWikiProvider.generate_client_id)
|
||||
oauth_client = OAuthClient.new(
|
||||
client_id: Wikis::XWikiProvider.generate_client_id,
|
||||
client_secret: Wikis::XWikiProvider.generate_client_secret
|
||||
)
|
||||
|
||||
update_via_turbo_stream(
|
||||
component: Wikis::Admin::Forms::OAuthClientFormComponent.new(@wiki_provider,
|
||||
@@ -92,7 +95,7 @@ module Wikis
|
||||
end
|
||||
|
||||
def oauth_client_params
|
||||
params.expect(oauth_client: [:client_id])
|
||||
params.expect(oauth_client: %i[client_id client_secret])
|
||||
end
|
||||
|
||||
def find_wiki_provider
|
||||
|
||||
@@ -45,7 +45,8 @@ module Wikis
|
||||
|
||||
class << self
|
||||
def registry_prefix = "xwiki"
|
||||
def generate_client_id = SecureRandom.uuid
|
||||
def generate_client_id = "openproject-#{SecureRandom.hex(8)}"
|
||||
def generate_client_secret = SecureRandom.hex(32)
|
||||
end
|
||||
|
||||
def configured?
|
||||
|
||||
@@ -35,8 +35,6 @@ module Wikis
|
||||
# OAuth2 configuration for XWiki's OIDC Provider extension.
|
||||
#
|
||||
# Deviations from a standard OAuth2 confidential client:
|
||||
# - Public client: no client_secret; token_endpoint_auth_method is :none.
|
||||
# - No pre-registration: XWiki accepts any client_id/redirect_uri; consent is stored on first auth.
|
||||
# - No refresh tokens: tokens are long-lived; re-auth via ensure_connection if revoked.
|
||||
# - No expires_in: tokens do not expire; expires_in is stored as nil.
|
||||
#
|
||||
@@ -69,9 +67,9 @@ module Wikis
|
||||
def basic_rack_oauth_client
|
||||
uri = provider_uri
|
||||
|
||||
# XWiki is a public client — no secret is used.
|
||||
Rack::OAuth2::Client.new(
|
||||
identifier: @oauth_client.client_id,
|
||||
secret: @oauth_client.client_secret,
|
||||
redirect_uri: @oauth_client.redirect_uri,
|
||||
scheme: uri.scheme,
|
||||
host: uri.host,
|
||||
|
||||
@@ -35,7 +35,7 @@ module Wikis
|
||||
module Queries
|
||||
class User < BaseQuery
|
||||
def call(auth_strategy:)
|
||||
url = "#{provider.url.chomp('/')}/rest/"
|
||||
url = "#{provider.url.chomp('/')}/rest/wikis/xwiki/user"
|
||||
Adapters::Authentication[auth_strategy].call do |http|
|
||||
handle_response(http.get(url))
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ module Wikis
|
||||
module OAuthClients
|
||||
class CreateService < ::OAuthClients::CreateService
|
||||
def initialize(**)
|
||||
super(contract_class: Wikis::OAuthClients::XWikiCreateContract, **)
|
||||
super(contract_class: ::OAuthClients::CreateContract, **)
|
||||
end
|
||||
|
||||
def attributes_service_class
|
||||
|
||||
@@ -32,7 +32,12 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<% html_title t(:label_administration), t(:project_module_wiki_platforms), page_title %>
|
||||
|
||||
<%= render(Primer::OpenProject::PageHeader.new) do |header| %>
|
||||
<% header.with_title { page_title } %>
|
||||
<% header.with_title do %>
|
||||
<%= page_title %>
|
||||
<%= render(Primer::Beta::Text.new(tag: :span, font_weight: :light, color: :muted)) do %>
|
||||
(<%= t("wikis.provider_types.#{@wiki_provider}.name") %>)
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%
|
||||
header.with_breadcrumbs(
|
||||
@@ -90,7 +95,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
render(Wikis::Admin::WikiProviderViewComponent.new(@wiki_provider, wizard: @wizard))
|
||||
end
|
||||
|
||||
page.with_sidebar(col_placement: :end, row_placement: :start) do
|
||||
page.with_sidebar(col_placement: :end, row_placement: :end) do
|
||||
render(Wikis::Admin::SidePanelComponent.new(@wiki_provider))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,7 +50,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
test_selector: "wiki-providers-create-new-button" }
|
||||
) do |menu|
|
||||
menu.with_item(
|
||||
label: I18n.t("activerecord.models.wikis/xwiki_provider"),
|
||||
label: I18n.t("wikis.provider_types.xwiki.name"),
|
||||
href: new_admin_settings_wiki_provider_path
|
||||
)
|
||||
end
|
||||
|
||||
@@ -27,17 +27,17 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title t(:label_administration), t(:project_module_wiki_platforms), t("wikis.admin.wiki_providers.label_new_xwiki_instance") %>
|
||||
<% html_title t(:label_administration), t(:project_module_wiki_platforms), t("wikis.admin.wiki_providers.label_new_provider") %>
|
||||
|
||||
<%= render(Primer::OpenProject::PageHeader.new) do |header| %>
|
||||
<% header.with_title(test_selector: "wiki-provider-new-page-header--title") do %>
|
||||
<%= t("wikis.admin.wiki_providers.label_new_xwiki_instance") %>
|
||||
<%= t("wikis.admin.wiki_providers.label_new_provider") %>
|
||||
<% end %>
|
||||
|
||||
<% header.with_breadcrumbs([
|
||||
{ href: admin_index_path, text: t(:label_administration) },
|
||||
{ href: admin_settings_wiki_providers_path, text: t(:project_module_wiki_platforms) },
|
||||
t("wikis.admin.wiki_providers.label_new_xwiki_instance")
|
||||
t("wikis.admin.wiki_providers.label_new_provider")
|
||||
]) %>
|
||||
|
||||
<% header.with_description(test_selector: "wiki-provider-new-page-header--description") do %>
|
||||
|
||||
@@ -35,8 +35,16 @@ en:
|
||||
buttons:
|
||||
connect_account: Connect %{provider} account
|
||||
done_continue: Done, continue
|
||||
open_wiki: Open wiki
|
||||
save_and_continue: Save and continue
|
||||
wiki_page: Wiki page
|
||||
instructions:
|
||||
xwiki:
|
||||
integration: XWiki Administration
|
||||
oauth_application_details_html: The client secret value will not be accessible again after you close this window. Please copy these values into the [XWiki OpenProject Integration settings](xwiki_admin_link).
|
||||
provider_types:
|
||||
xwiki:
|
||||
name: XWiki
|
||||
delete_relation_page_link_confirmation_dialog:
|
||||
title: Delete related wiki page link
|
||||
heading: Delete related wiki page link?
|
||||
@@ -80,12 +88,15 @@ en:
|
||||
inline wiki page link will no longer be accessible. This action is irreversible.
|
||||
forms:
|
||||
general_info_form_component:
|
||||
xwiki_instance_description: Please make sure you have administration privileges in your XWiki instance before doing the setup.
|
||||
provider_description: Please make sure you have administration privileges in your XWiki instance before doing the setup.
|
||||
oauth_application_form_component:
|
||||
application_id: Application ID
|
||||
application_secret: Application secret
|
||||
application_id: OpenProject OAuth Application ID
|
||||
application_secret: OpenProject OAuth Application secret
|
||||
oauth_client_form_component:
|
||||
client_id: Client ID
|
||||
client_id: Wiki OAuth Client ID
|
||||
client_secret: Wiki OAuth Client secret
|
||||
redirect_uri: Redirect URI
|
||||
redirect_uri_caption: Copy this value into the Redirect URI field of your XWiki OIDC client registration.
|
||||
health_status:
|
||||
show:
|
||||
actions:
|
||||
@@ -98,10 +109,12 @@ en:
|
||||
title: Health Report
|
||||
oauth_application_info_component:
|
||||
confirm_replace_oauth_application: This action will reset the current OAuth credentials. After confirming you will have to reenter the credentials in your XWiki instance and all users will have to reauthorize. Are you sure you want to proceed?
|
||||
label_oauth_client_id: OAuth Client ID
|
||||
label_pending: Pending
|
||||
replace_oauth_application: Replace OpenProject OAuth application
|
||||
oauth_client_info_component:
|
||||
confirm_replace_oauth_client: This action will reset the current XWiki OAuth credentials. All users will need to reauthorize against XWiki. Are you sure you want to proceed?
|
||||
label_oauth_client_id: OAuth Client ID
|
||||
label_pending: Pending
|
||||
replace_oauth_client: Replace XWiki OAuth application
|
||||
side_panel:
|
||||
@@ -120,7 +133,7 @@ en:
|
||||
index_description: Add an external wiki service to link work packages to existing wiki pages or create new ones directly from OpenProject.
|
||||
label_add_new: Add new wiki provider
|
||||
label_edit: Edit XWiki provider
|
||||
label_new_xwiki_instance: New XWiki provider
|
||||
label_new_provider: New XWiki provider
|
||||
label_wiki_platform: Wiki provider
|
||||
name_caption: Give your storage a name so that users can differentiate between multiple wiki platforms.
|
||||
name_placeholder: XWiki knowledge base
|
||||
@@ -128,15 +141,14 @@ en:
|
||||
oauth:
|
||||
openproject_oauth: OpenProject OAuth
|
||||
sections:
|
||||
general_information: Basic details
|
||||
general_information: General information
|
||||
oauth_configuration: OAuth configuration
|
||||
url_caption: Please add the host address of your wiki platform including the https://. It should not be longer than 255 characters.
|
||||
xwiki_instance: XWiki Instance
|
||||
xwiki:
|
||||
oauth:
|
||||
openproject_oauth_description: Allow XWiki to access OpenProject data using an OAuth application. Copy the credentials below into your XWiki instance.
|
||||
provider_oauth: XWiki OAuth
|
||||
provider_oauth_description: Allow OpenProject to access XWiki data using OAuth. A client ID is automatically generated to identify OpenProject to XWiki — no manual configuration is needed on the XWiki side.
|
||||
provider_oauth: Wiki OAuth
|
||||
provider_oauth_description: Allow OpenProject to access XWiki data using OAuth. A client ID and client secret have been pre-generated for you — copy them along with the redirect URI into your XWiki OIDC client registration. You can change the client ID and secret if needed.
|
||||
openproject_oauth_description: Allow XWiki to access OpenProject data using an OAuth.
|
||||
xwiki_oauth: XWiki OAuth
|
||||
xwiki_oauth_description: Allow OpenProject to access XWiki data using an OAuth.
|
||||
|
||||
@@ -65,9 +65,11 @@ RSpec.describe Wikis::Admin::OAuthApplicationInfoComponent, type: :component do
|
||||
expect(page).to have_text(I18n.t(:label_completed))
|
||||
end
|
||||
|
||||
it "renders the description" do
|
||||
it "renders the oauth application id" do
|
||||
render_inline(described_class.new(wiki_provider))
|
||||
expect(page).to have_text(I18n.t("wikis.admin.wiki_providers.xwiki.oauth.openproject_oauth_description"))
|
||||
expect(page).to have_text(
|
||||
"#{I18n.t('wikis.admin.oauth_application_info_component.label_oauth_client_id')}: #{oauth_application.uid}"
|
||||
)
|
||||
end
|
||||
|
||||
it "renders a sync button with a confirm dialog" do
|
||||
|
||||
@@ -63,9 +63,11 @@ RSpec.describe Wikis::Admin::OAuthClientInfoComponent, type: :component do
|
||||
expect(page).to have_text(I18n.t(:label_completed))
|
||||
end
|
||||
|
||||
it "renders the description" do
|
||||
it "renders the oauth client id" do
|
||||
render_inline(described_class.new(wiki_provider))
|
||||
expect(page).to have_text(I18n.t("wikis.admin.wiki_providers.xwiki.oauth.provider_oauth_description"))
|
||||
expect(page).to have_text(
|
||||
"#{I18n.t('wikis.admin.oauth_client_info_component.label_oauth_client_id')}: #{oauth_client.client_id}"
|
||||
)
|
||||
end
|
||||
|
||||
it "renders a sync icon button with a confirm dialog" do
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# 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"
|
||||
require_module_spec_helper
|
||||
require "contracts/shared/model_contract_shared_context"
|
||||
|
||||
RSpec.describe Wikis::OAuthClients::XWikiCreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
let(:current_user) { create(:admin) }
|
||||
let(:client_id) { SecureRandom.uuid }
|
||||
let(:client_secret) { nil }
|
||||
let(:integration) { create(:xwiki_provider) }
|
||||
let(:oauth_client) { build(:oauth_client, client_id:, client_secret:, integration:) }
|
||||
|
||||
let(:contract) { described_class.new(oauth_client, current_user) }
|
||||
|
||||
describe "client_secret" do
|
||||
context "when absent (nil)" do
|
||||
include_examples "contract is valid"
|
||||
end
|
||||
|
||||
context "when empty string" do
|
||||
let(:client_secret) { "" }
|
||||
|
||||
include_examples "contract is valid"
|
||||
end
|
||||
|
||||
context "when too long" do
|
||||
let(:client_secret) { "X" * 257 }
|
||||
|
||||
include_examples "contract is invalid", client_secret: :too_long
|
||||
end
|
||||
end
|
||||
end
|
||||
+4
-2
@@ -32,7 +32,9 @@ require "spec_helper"
|
||||
|
||||
RSpec.describe Wikis::Adapters::Providers::XWiki::OAuthConfiguration do
|
||||
let(:wiki_provider) { build_stubbed(:xwiki_provider, url: "https://xwiki.example.com/xwiki") }
|
||||
let(:oauth_client) { build_stubbed(:oauth_client, client_id: "xwiki-uuid", integration: wiki_provider) }
|
||||
let(:oauth_client) do
|
||||
build_stubbed(:oauth_client, client_id: "xwiki-uuid", client_secret: "xwiki-secret", integration: wiki_provider)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(wiki_provider).to receive(:oauth_client).and_return(oauth_client)
|
||||
@@ -90,7 +92,7 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::OAuthConfiguration do
|
||||
it "configures the rack client with correct attributes" do
|
||||
expect(rack_client).to have_attributes(
|
||||
identifier: "xwiki-uuid",
|
||||
secret: nil,
|
||||
secret: "xwiki-secret",
|
||||
token_endpoint: "/xwiki/oidc/token",
|
||||
authorization_endpoint: "/xwiki/oidc/authorization"
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::User, :webmock do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
let(:oauth_client) { build_stubbed(:oauth_client) }
|
||||
let(:wiki_provider) { build_stubbed(:xwiki_provider, url: "https://xwiki.local/") }
|
||||
let(:rest_url) { "https://xwiki.local/rest/" }
|
||||
let(:user_url) { "https://xwiki.local/rest/wikis/xwiki/user" }
|
||||
let(:auth_strategy) { Wikis::Adapters::Input::AuthStrategy.build(key: :bearer_token, user:, provider: wiki_provider).value! }
|
||||
|
||||
subject(:query) { described_class.new(model: wiki_provider) }
|
||||
@@ -51,9 +51,9 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::User, :webmock do
|
||||
end
|
||||
|
||||
describe "#call" do
|
||||
context "when the request succeeds with xwiki-user header" do
|
||||
context "when the request succeeds with an xwiki-user header" do
|
||||
before do
|
||||
stub_request(:get, rest_url)
|
||||
stub_request(:get, user_url)
|
||||
.with(headers: { "Authorization" => "Bearer some-token" })
|
||||
.to_return(status: 200, body: "", headers: { "xwiki-user" => "XWiki.admin" })
|
||||
end
|
||||
@@ -65,10 +65,10 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::User, :webmock do
|
||||
end
|
||||
end
|
||||
|
||||
context "when the token is absent or invalid (XWiki returns 200 without xwiki-user header)" do
|
||||
context "when the response is missing the xwiki-user header" do
|
||||
before do
|
||||
stub_request(:get, rest_url)
|
||||
.to_return(status: 200, body: "", headers: {})
|
||||
stub_request(:get, user_url)
|
||||
.to_return(status: 200, body: "")
|
||||
end
|
||||
|
||||
it "returns Failure with :unauthorized code" do
|
||||
@@ -80,7 +80,7 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::User, :webmock do
|
||||
|
||||
context "when XWiki returns a non-2xx status" do
|
||||
before do
|
||||
stub_request(:get, rest_url).to_return(status: 500, body: "Internal Server Error")
|
||||
stub_request(:get, user_url).to_return(status: 401, body: "Unauthorized")
|
||||
end
|
||||
|
||||
it "returns Failure with :request_failed code" do
|
||||
@@ -91,7 +91,7 @@ RSpec.describe Wikis::Adapters::Providers::XWiki::Queries::User, :webmock do
|
||||
end
|
||||
|
||||
context "when a network error occurs" do
|
||||
before { stub_request(:get, rest_url).to_timeout }
|
||||
before { stub_request(:get, user_url).to_timeout }
|
||||
|
||||
it "returns Failure with :connection_error code" do
|
||||
result = query.call(auth_strategy:)
|
||||
|
||||
Reference in New Issue
Block a user