Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/contracts/oauth_clients/create_contract.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ class CreateContract < ::ModelContract
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

module Wikis::Admin::Forms
class OAuthApplicationFormComponent < Wikis::Admin::WikiProviderComponent
OPENPROJECT_PLUGIN_ADMIN_PATH = "/bin/admin/XWiki/XWikiPreferences?editor=globaladmin&section=OpenProject"

def self.wrapper_key = :wiki_provider_oauth_application_section

delegate :oauth_application, to: :wiki_provider
Expand All @@ -43,5 +45,9 @@ def done_button_path
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
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ def cancel_button_path
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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ class OAuthClientsController < ApplicationController
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,
Expand Down Expand Up @@ -92,7 +95,7 @@ def save_oauth_client
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
Expand Down
3 changes: 2 additions & 1 deletion modules/wikis/app/models/wikis/xwiki_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class XWikiProvider < Provider

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?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ module XWiki
# 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.
#
Expand Down Expand Up @@ -69,9 +67,9 @@ def authorization_uri(state: nil)
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module XWiki
module Queries
class User < BaseQuery
def call(auth_strategy:)
url = "#{provider.url.chomp('/')}/rest/"
url = "#{provider.url.chomp('/')}/rest/wikis/xwiki/user"
Comment thread
NobodysNightmare marked this conversation as resolved.
Adapters::Authentication[auth_strategy].call do |http|
handle_response(http.get(url))
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Comment thread
NobodysNightmare marked this conversation as resolved.
render(Wikis::Admin::SidePanelComponent.new(@wiki_provider))
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
Expand Down
Loading
Loading