Skip to content

Commit

Permalink
Allow to configure authentication method through UI
Browse files Browse the repository at this point in the history
  • Loading branch information
NobodysNightmare committed Feb 3, 2025
1 parent 141b73d commit a92505f
Show file tree
Hide file tree
Showing 19 changed files with 549 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module Peripherals
namespace("forms") do
register(:automatically_managed_folders, ::Storages::Admin::Forms::AutomaticallyManagedProjectFoldersFormComponent)
register(:general_information, ::Storages::Admin::Forms::GeneralInfoFormComponent)
register(:nextcloud_audience, ::Storages::Admin::Forms::NextcloudAudienceFormComponent)
register(:oauth_application, ::Storages::Admin::OAuthApplicationInfoCopyComponent)
register(:oauth_client, ::Storages::Admin::Forms::OAuthClientFormComponent)
end
Expand All @@ -69,6 +70,7 @@ module Peripherals

register(:automatically_managed_folders, ::Storages::Admin::AutomaticallyManagedProjectFoldersInfoComponent)
register(:general_information, ::Storages::Admin::GeneralInfoComponent)
register(:nextcloud_audience, ::Storages::Admin::NextcloudAudienceInfoComponent)
register(:oauth_application, ::Storages::Admin::OAuthApplicationInfoComponent)
register(:oauth_client, ::Storages::Admin::OAuthClientInfoComponent)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,28 @@ module Peripherals
class NextcloudStorageWizard < Wizard
step :general_information, completed_if: ->(storage) { storage.host.present? && storage.name.present? }

# Two-Way OAuth 2.0

step :oauth_application,
section: :oauth_configuration,
if: ->(storage) { !storage.authenticate_via_idp? },
completed_if: ->(storage) { storage.oauth_application.present? },
preparation: :prepare_oauth_application

step :oauth_client,
section: :oauth_configuration,
if: ->(storage) { !storage.authenticate_via_idp? },
completed_if: ->(storage) { storage.oauth_client.present? },
preparation: ->(storage) { storage.build_oauth_client }

# OAuth 2.0 SSO

step :nextcloud_audience,
section: :oauth_configuration,
if: ->(storage) { storage.authenticate_via_idp? },
completed_if: ->(storage) { storage.nextcloud_audience.present? },
preparation: :prepare_oauth_application

step :automatically_managed_folders,
completed_if: ->(storage) { !storage.automatic_management_unspecified? },
preparation: :prepare_storage_for_automatic_management_form
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,23 @@
general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderHostInputForm.new(form))
end

general_info_row.with_row(mb: 3) do
render(Storages::Admin::NextcloudAuthenticationMethodInputForm.new(form))
end
end

if storage.provider_type_one_drive?
general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderDriveIdInputForm.new(form))
end

if model.errors.any?
general_info_row.with_row(mb: 3) do
render(Primer::Beta::Text.new) { model.errors.full_messages }
end
end

general_info_row.with_row(mb: 3) do
render(Storages::Admin::ProviderTenantIdInputForm.new(form))
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,18 @@ class GeneralInfoFormComponent < ApplicationComponent

alias_method :storage, :model

options form_method: :post,
submit_button_disabled: false,
options submit_button_disabled: false,
in_wizard: false

def self.wrapper_key = :storage_general_info_section

def form_url
query = { continue_wizard: storage.id } if in_wizard

case form_method
when :get, :post
admin_settings_storages_path(query)
when :patch, :put
if storage.persisted?
admin_settings_storage_path(storage, query)
else
admin_settings_storages_path(query)
end
end

Expand All @@ -68,6 +66,14 @@ def cancel_button_options

private

def form_method
if storage.persisted?
:patch
else
:post
end
end

def cancel_button_path
options.fetch(:cancel_button_path) do
if storage.persisted?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<%=
component_wrapper(tag: 'turbo-frame') do
render(Primer::Beta::Text.new(tag: :div, test_selector: 'storage-nextcloud-audience-form')) do
primer_form_with(
model:,
url: form_url,
method: :patch,
data: { turbo_frame: "page-content" }
) do |form|
flex_layout do |general_info_row|
general_info_row.with_row(mb: 3) do
render(Storages::Admin::NextcloudAudienceInputForm.new(form))
end

general_info_row.with_row do
render(
Storages::Admin::SubmitOrCancelForm.new(
form,
storage:,
submit_button_options:,
cancel_button_options:
)
)
end
end
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 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 Storages::Admin::Forms
class NextcloudAudienceFormComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
include OpTurbo::Streamable

alias_method :storage, :model

options submit_button_disabled: false,
in_wizard: false

def self.wrapper_key = :storage_nextcloud_audience_section

def form_url
query = { continue_wizard: storage.id } if in_wizard
admin_settings_storage_path(storage, query)
end

def submit_button_options
{ disabled: submit_button_disabled }
end

def cancel_button_options
{ href: cancel_button_path, data: { turbo_stream: true } }
end

private

def cancel_button_path
edit_admin_settings_storage_path(storage)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<%=
component_wrapper(tag: 'turbo-frame') 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, test_selector: 'nextcloud-audience-label')) { I18n.t('storages.file_storage_view.nextcloud_audience') })
concat(configuration_check_label_for(:nextcloud_audience_configured))
end

grid.with_area(:description, tag: :div, color: :subtle, test_selector: 'nextcloud-audience-description') do
concat(render(Primer::Beta::Text.new) {
if storage.nextcloud_audience.present?
I18n.t('storages.file_storage_view.nextcloud_audience_description', audience: storage.nextcloud_audience)
else
I18n.t('storages.file_storage_view.nextcloud_audience_blank')
end
})
end

if editable_storage?
grid.with_area(:"icon-button", tag: :div, color: :muted) do
flex_layout(justify_content: :flex_end) do |icons_container|
icons_container.with_column do
render(
Primer::Beta::IconButton.new(
icon: :pencil,
tag: :a,
scheme: :invisible,
href: edit_nextcloud_audience_admin_settings_storage_path(storage),
aria: { label: I18n.t('storages.label_edit_nextcloud_audience') },
test_selector: 'storage-edit-nextcloud-audience-button',
data: { turbo_stream: true }
)
)
end
end
end
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 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 Storages
module Admin
class NextcloudAudienceInfoComponent < ApplicationComponent
include OpPrimer::ComponentHelpers
include OpTurbo::Streamable
include StorageViewInformation

alias_method :storage, :model

def self.wrapper_key = :storage_nextcloud_audience_section
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class NextcloudContract < ::ModelContract
validates :authentication_method, presence: true, inclusion: { in: ::Storages::NextcloudStorage::AUTHENTICATION_METHODS }

attribute :nextcloud_audience
validates :nextcloud_audience, presence: true, if: :nextcloud_storage_authenticate_via_idp?

attribute :automatically_managed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Storages::Admin::StoragesController < ApplicationController
# and set the @<controller_name> variable to the object referenced in the URL.
before_action :require_admin
before_action :find_model_object,
only: %i[show_oauth_application destroy edit edit_host confirm_destroy update
only: %i[show_oauth_application destroy edit edit_host edit_nextcloud_audience confirm_destroy update
change_health_notifications_enabled replace_oauth_application]
before_action :ensure_valid_wizard_parameters, only: [:new]
before_action :require_ee_token_for_one_drive, only: [:new]
Expand Down Expand Up @@ -112,16 +112,17 @@ def edit

def edit_host
update_via_turbo_stream(
component: Storages::Admin::Forms::GeneralInfoFormComponent.new(
@storage,
form_method: :patch,
cancel_button_path: edit_admin_settings_storage_path(@storage)
)
component: Storages::Admin::Forms::GeneralInfoFormComponent.new(@storage)
)

respond_with_turbo_streams
end

def edit_nextcloud_audience
update_via_turbo_stream(component: Storages::Admin::Forms::NextcloudAudienceFormComponent.new(@storage))
respond_with_turbo_streams
end

def update # rubocop:disable Metrics/AbcSize
service_result = ::Storages::Storages::UpdateService
.new(user: current_user, model: @storage)
Expand All @@ -136,10 +137,8 @@ def update # rubocop:disable Metrics/AbcSize
end
else
update_via_turbo_stream(
component: Storages::Admin::Forms::GeneralInfoFormComponent.new(
component: ::Storages::Peripherals::Registry.resolve("#{@storage}.components.forms.general_information").new(
@storage,
form_method: :patch,
cancel_button_path: edit_admin_settings_storage_path(@storage),
in_wizard: params[:continue_wizard].present?
)
)
Expand Down Expand Up @@ -243,6 +242,8 @@ def permitted_storage_params(model_parameter_name = storage_provider_parameter_n
.permit("name",
"provider_type",
"host",
"authentication_method",
"nextcloud_audience",
"oauth_client_id",
"oauth_client_secret",
"tenant_id",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#-- 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 Storages::Admin
class NextcloudAudienceInputForm < ApplicationForm
form do |storage_form|
storage_form.text_field(
name: :nextcloud_audience,
label: I18n.t("activerecord.attributes.storages/nextcloud_storage.nextcloud_audience"),
required: true,
caption: I18n.t("storages.instructions.nextcloud.nextcloud_audience"),
placeholder: I18n.t("storages.instructions.nextcloud.nextcloud_audience_placeholder"),
input_width: :large
)
end
end
end
Loading

0 comments on commit a92505f

Please sign in to comment.