mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Add UI for SCIM Clients
Allowing to manage SCIM clients through the UI, including all the authentication methods and their related "behind the scenes" setup, i.e. service account, oauth application and access tokens.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::InputGroup.new(input_width: :large)) do |input_group|
|
||||
input_group.with_text_input(
|
||||
name: :client_id,
|
||||
label: Doorkeeper::Application.human_attribute_name(:uid),
|
||||
visually_hide_label: false,
|
||||
value: model.oauth_application.uid
|
||||
)
|
||||
input_group.with_trailing_action_clipboard_copy_button(
|
||||
value: model.oauth_application.uid,
|
||||
aria: {
|
||||
label: I18n.t("button_copy_to_clipboard")
|
||||
}
|
||||
)
|
||||
end
|
||||
%>
|
||||
@@ -0,0 +1,36 @@
|
||||
# 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 Admin
|
||||
module ScimClients
|
||||
class ClientIdComponent < ApplicationComponent
|
||||
end
|
||||
end
|
||||
end
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= render(Primer::OpenProject::FeedbackDialog.new(title: t(".title"), size: :large, classes: "Overlay--size-large-portrait", **system_arguments)) do |dialog|
|
||||
dialog.with_feedback_message(icon_arguments: { icon: :"check-circle" }) do |message|
|
||||
message.with_heading(tag: :h2).with_content(t(".heading"))
|
||||
end
|
||||
|
||||
dialog.with_additional_details(display: :block) do
|
||||
render(Primer::OpenProject::FlexLayout.new) do |layout|
|
||||
layout.with_row do
|
||||
render(Primer::OpenProject::InputGroup.new) do |input_group|
|
||||
input_group.with_text_input(
|
||||
name: :client_id,
|
||||
label: Doorkeeper::Application.human_attribute_name(:uid),
|
||||
visually_hide_label: false,
|
||||
value: model.oauth_application.uid
|
||||
)
|
||||
input_group.with_trailing_action_clipboard_copy_button(
|
||||
value: model.oauth_application.uid,
|
||||
aria: { label: I18n.t("button_copy_to_clipboard") }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
layout.with_row do
|
||||
render(Primer::OpenProject::InputGroup.new) do |input_group|
|
||||
input_group.with_text_input(
|
||||
name: :client_secret,
|
||||
label: Doorkeeper::Application.human_attribute_name(:secret),
|
||||
visually_hide_label: false,
|
||||
value: model.oauth_application.secret
|
||||
)
|
||||
input_group.with_trailing_action_clipboard_copy_button(
|
||||
value: model.oauth_application.secret,
|
||||
aria: { label: I18n.t("button_copy_to_clipboard") }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
layout.with_row(mt: 3) do
|
||||
render(Primer::Alpha::Banner.new(scheme: :warning, icon: :alert)) { t(".one_time_hint") }
|
||||
end
|
||||
end
|
||||
end
|
||||
end %>
|
||||
@@ -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 Admin
|
||||
module ScimClients
|
||||
class CreatedClientCredentialsDialogComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
|
||||
TEST_SELECTOR = "op-scim-clients--created-client-credentials-dialog"
|
||||
|
||||
def system_arguments
|
||||
options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= render(Primer::OpenProject::FeedbackDialog.new(title: t(".title"), size: :large, **system_arguments)) do |dialog|
|
||||
dialog.with_feedback_message(icon_arguments: { icon: :"check-circle" }) do |message|
|
||||
message.with_heading(tag: :h2).with_content(t(".heading"))
|
||||
end
|
||||
|
||||
dialog.with_additional_details(display: :block) do
|
||||
concat(
|
||||
render(Primer::OpenProject::InputGroup.new) do |input_group|
|
||||
input_group.with_text_input(
|
||||
name: :token,
|
||||
label: t(".label_token"),
|
||||
visually_hide_label: false,
|
||||
value: model.token
|
||||
)
|
||||
input_group.with_trailing_action_clipboard_copy_button(
|
||||
value: model.token,
|
||||
aria: { label: I18n.t("button_copy_to_clipboard") }
|
||||
)
|
||||
end
|
||||
)
|
||||
|
||||
concat(render(Primer::Alpha::Banner.new(scheme: :warning, icon: :alert, mt: 3)) { t(".one_time_hint") })
|
||||
end
|
||||
end %>
|
||||
@@ -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 Admin
|
||||
module ScimClients
|
||||
class CreatedTokenDialogComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
|
||||
TEST_SELECTOR = "op-scim-clients--created-static-token-dialog"
|
||||
|
||||
def system_arguments
|
||||
options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%=
|
||||
render(
|
||||
Primer::OpenProject::DangerDialog.new(
|
||||
title: t(".title"),
|
||||
form_arguments:,
|
||||
test_selector: TEST_SELECTOR
|
||||
)
|
||||
) do |dialog|
|
||||
dialog.with_confirmation_message do |message|
|
||||
message.with_heading(tag: :h2) { t(".heading") }
|
||||
message.with_description_content(t(".description"))
|
||||
end
|
||||
end
|
||||
%>
|
||||
@@ -0,0 +1,46 @@
|
||||
# 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 Admin
|
||||
module ScimClients
|
||||
class DeleteScimClientDialogComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
|
||||
TEST_SELECTOR = "op-scim-clients--delete-client-dialog"
|
||||
|
||||
def form_arguments
|
||||
{
|
||||
action: admin_scim_client_path(model),
|
||||
method: :delete
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%=
|
||||
component_wrapper(tag: "turbo-frame") do
|
||||
settings_primer_form_with(**form_options) do |f|
|
||||
render(ScimClients::Form.new(f))
|
||||
end
|
||||
end
|
||||
%>
|
||||
@@ -0,0 +1,63 @@
|
||||
# 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 Admin::ScimClients
|
||||
class FormComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
include OpPrimer::ComponentHelpers
|
||||
include OpTurbo::Streamable
|
||||
|
||||
def self.wrapper_key = :scim_clients_form
|
||||
|
||||
private
|
||||
|
||||
def form_options
|
||||
form_target.merge(stimulus_controller_options)
|
||||
.merge(model:)
|
||||
end
|
||||
|
||||
def form_target
|
||||
if model.new_record?
|
||||
{ method: :post, url: admin_scim_clients_path }
|
||||
else
|
||||
{ method: :patch, url: admin_scim_client_path(model) }
|
||||
end
|
||||
end
|
||||
|
||||
def stimulus_controller_options
|
||||
{
|
||||
data: {
|
||||
controller: "scim-clients--form-inputs",
|
||||
turbo_frame: "_top"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,44 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%=
|
||||
render(
|
||||
Primer::OpenProject::DangerDialog.new(
|
||||
title: t(".title"),
|
||||
confirm_button_text: t(".confirm_button"),
|
||||
form_arguments:,
|
||||
test_selector: TEST_SELECTOR
|
||||
)
|
||||
) do |dialog|
|
||||
dialog.with_confirmation_message do |message|
|
||||
message.with_heading(tag: :h2) { t(".heading") }
|
||||
message.with_description_content(t(".description"))
|
||||
end
|
||||
end
|
||||
%>
|
||||
+22
-19
@@ -28,28 +28,31 @@
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
module ScimClients
|
||||
FormModel = Data.define(:name, :auth_provider_id, :authentication_method, :jwt_sub) do
|
||||
extend ActiveModel::Naming
|
||||
module Admin
|
||||
module ScimClients
|
||||
class RevokeStaticTokenDialogComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
|
||||
class << self
|
||||
def from_client(client)
|
||||
jwt_sub = client.service_account&.active_user_auth_provider_link&.external_id
|
||||
new(
|
||||
name: client.name,
|
||||
auth_provider_id: client.auth_provider_id,
|
||||
authentication_method: client.authentication_method,
|
||||
jwt_sub:
|
||||
)
|
||||
TEST_SELECTOR = "op-scim-clients--revoke-static-token-dialog"
|
||||
|
||||
def initialize(model, scim_client_id:, turbo_frame: nil)
|
||||
super(model)
|
||||
|
||||
@scim_client_id = scim_client_id
|
||||
@turbo_frame = turbo_frame
|
||||
end
|
||||
|
||||
def from_params(params)
|
||||
new(
|
||||
name: params[:name],
|
||||
auth_provider_id: params[:auth_provider_id],
|
||||
authentication_method: params[:authentication_method].to_s,
|
||||
jwt_sub: params[:jwt_sub]
|
||||
)
|
||||
def form_arguments
|
||||
{
|
||||
action: admin_scim_client_static_token_path(model, scim_client_id: @scim_client_id),
|
||||
method: :delete
|
||||
}.merge(turbo_frame_arguments)
|
||||
end
|
||||
|
||||
def turbo_frame_arguments
|
||||
return {} if @turbo_frame.nil?
|
||||
|
||||
{ data: { turbo_frame: @turbo_frame } }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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 Admin::ScimClients
|
||||
class RowComponent < OpPrimer::BorderBoxRowComponent
|
||||
def name
|
||||
render(Primer::Beta::Link.new(href: edit_admin_scim_client_path(model), font_weight: :bold)) { model.name }
|
||||
end
|
||||
|
||||
def user_count
|
||||
return "—" if model.auth_provider.nil?
|
||||
|
||||
model.auth_provider.users.count
|
||||
end
|
||||
|
||||
def authentication_method
|
||||
t("admin.scim_clients.authentication_methods.#{model.authentication_method}")
|
||||
end
|
||||
|
||||
def created_at
|
||||
helpers.format_date(model.created_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
# 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 Admin::ScimClients
|
||||
class TableComponent < OpPrimer::BorderBoxTableComponent
|
||||
columns :name, :user_count, :authentication_method, :created_at
|
||||
mobile_labels :user_count, :authentication_method, :created_at
|
||||
|
||||
def mobile_title
|
||||
ScimClient.model_name.human(count: 2)
|
||||
end
|
||||
|
||||
def row_class
|
||||
RowComponent
|
||||
end
|
||||
|
||||
def headers
|
||||
[
|
||||
[:name, { caption: ScimClient.human_attribute_name(:name) }],
|
||||
[:user_count, { caption: t(".user_count") }],
|
||||
[:authentication_method, { caption: ScimClient.human_attribute_name(:authentication_method) }],
|
||||
[:created_at, { caption: ScimClient.human_attribute_name(:created_at) }]
|
||||
]
|
||||
end
|
||||
|
||||
def blank_title
|
||||
t(".blank_slate.title")
|
||||
end
|
||||
|
||||
def blank_description
|
||||
t(".blank_slate.description")
|
||||
end
|
||||
|
||||
def blank_icon
|
||||
:key
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<%= component_wrapper(tag: "turbo-frame") do %>
|
||||
<%= render(Primer::Beta::Subhead.new(spacious: true)) do |component|
|
||||
component.with_heading { t(".heading") }
|
||||
component.with_description { t(".description") }
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render(Admin::ScimClients::TokenTableComponent.new(rows: access_tokens)) %>
|
||||
|
||||
<%= primer_form_with(url: admin_scim_client_static_tokens_path(model), method: :post) do %>
|
||||
<%= render(
|
||||
Primer::Beta::Button.new(
|
||||
mt: 3,
|
||||
type: :submit,
|
||||
"aria-label": t(".label_aria_add_token"),
|
||||
test_selector: "op-scim-clients--add-token-button"
|
||||
)
|
||||
) do |button|
|
||||
button.with_leading_visual_icon(icon: :plus)
|
||||
t(".label_add_token")
|
||||
end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -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 Admin
|
||||
module ScimClients
|
||||
class TokenListComponent < ApplicationComponent
|
||||
include OpTurbo::Streamable
|
||||
|
||||
def self.wrapper_key = :scim_clients_token_list
|
||||
|
||||
def access_tokens
|
||||
model.access_tokens.order(created_at: :desc)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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.
|
||||
#++
|
||||
|
||||
module Admin::ScimClients
|
||||
class TokenRowComponent < OpPrimer::BorderBoxRowComponent
|
||||
def created_at
|
||||
format_date(model.created_at)
|
||||
end
|
||||
|
||||
def expires_at
|
||||
if model.revoked?
|
||||
t("admin.scim_clients.token_table_component.revoked", date: format_date(model.revoked_at))
|
||||
elsif model.expired?
|
||||
t("admin.scim_clients.token_table_component.expired", date: format_date(model.expires_at))
|
||||
else
|
||||
format_date(model.expires_at)
|
||||
end
|
||||
end
|
||||
|
||||
def button_links
|
||||
[revoke_button] # invisible button outside of menu
|
||||
end
|
||||
|
||||
def revoke_button
|
||||
return if model.revoked? || model.expired?
|
||||
|
||||
render(
|
||||
Primer::Beta::IconButton.new(
|
||||
scheme: :invisible,
|
||||
"aria-label": t("button_revoke"),
|
||||
icon: :"no-entry",
|
||||
tag: :a,
|
||||
href: deletion_dialog_admin_scim_client_static_token_path(model, scim_client_id: scim_client.id,
|
||||
target: TokenListComponent.wrapper_key),
|
||||
data: { controller: "async-dialog" },
|
||||
test_selector: "op-scim-clients--revoke-token-button"
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scim_client
|
||||
model.application.integration
|
||||
end
|
||||
|
||||
def format_date(date)
|
||||
helpers.format_date(date)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
# 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 Admin::ScimClients
|
||||
class TokenTableComponent < OpPrimer::BorderBoxTableComponent
|
||||
columns :created_at, :expires_at
|
||||
mobile_labels :created_at, :expires_at
|
||||
|
||||
def mobile_title
|
||||
t(".title")
|
||||
end
|
||||
|
||||
def row_class
|
||||
TokenRowComponent
|
||||
end
|
||||
|
||||
def headers
|
||||
[
|
||||
[:created_at, { caption: Doorkeeper::AccessToken.human_attribute_name(:created_at) }],
|
||||
[:expires_at, { caption: Doorkeeper::AccessToken.human_attribute_name(:expires_at) }]
|
||||
]
|
||||
end
|
||||
|
||||
def blank_title
|
||||
t(".blank_slate.title")
|
||||
end
|
||||
|
||||
def blank_description
|
||||
t(".blank_slate.description")
|
||||
end
|
||||
|
||||
def has_actions?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,6 +29,17 @@
|
||||
#++
|
||||
|
||||
module ScimClients
|
||||
class CreateContract < BaseContract
|
||||
class CreateContract < ModelContract
|
||||
attribute :name
|
||||
validates :name, presence: true
|
||||
|
||||
attribute :auth_provider
|
||||
validates :auth_provider, presence: true
|
||||
|
||||
attribute :authentication_method
|
||||
validates :authentication_method, inclusion: { in: ScimClient.authentication_methods.keys }
|
||||
|
||||
attribute :jwt_sub
|
||||
validates :jwt_sub, presence: true, if: -> { @model.authentication_method_sso? }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#++
|
||||
|
||||
module ScimClients
|
||||
class UpdateContract < BaseContract
|
||||
class UpdateContract < CreateContract
|
||||
attribute :authentication_method, writable: false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# 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 Admin
|
||||
class ScimClientStaticTokensController < ::ApplicationController
|
||||
include OpTurbo::ComponentStream
|
||||
|
||||
before_action :require_admin
|
||||
|
||||
def create
|
||||
scim_client = ScimClient.find(params[:scim_client_id])
|
||||
result = ::ScimClients::GenerateStaticTokenService.new(scim_client).call
|
||||
|
||||
update_via_turbo_stream(component: Admin::ScimClients::TokenListComponent.new(scim_client))
|
||||
|
||||
respond_with_dialog ScimClients::CreatedTokenDialogComponent.new(result.result)
|
||||
end
|
||||
|
||||
def deletion_dialog
|
||||
respond_with_dialog ScimClients::RevokeStaticTokenDialogComponent.new(
|
||||
Doorkeeper::AccessToken.find(params[:id]),
|
||||
scim_client_id: params[:scim_client_id],
|
||||
turbo_frame: params[:target].presence
|
||||
)
|
||||
end
|
||||
|
||||
def destroy
|
||||
token = Doorkeeper::AccessToken.find(params[:id])
|
||||
scim_client = ScimClient.find(params[:scim_client_id])
|
||||
|
||||
::ScimClients::RevokeStaticTokenService.new(scim_client).call(token)
|
||||
|
||||
redirect_to edit_admin_scim_client_path(scim_client)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,132 @@
|
||||
# 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 Admin
|
||||
class ScimClientsController < ::ApplicationController
|
||||
include OpTurbo::ComponentStream
|
||||
|
||||
before_action :require_admin
|
||||
|
||||
menu_item :scim_clients
|
||||
|
||||
layout "admin"
|
||||
|
||||
def index
|
||||
@scim_clients = ScimClient.order(:name)
|
||||
end
|
||||
|
||||
def new
|
||||
@scim_client = ScimClient.new(authentication_method: :oauth2_token)
|
||||
end
|
||||
|
||||
def edit
|
||||
@scim_client = ScimClient.find(params[:id])
|
||||
|
||||
first_time_setup(@scim_client)
|
||||
end
|
||||
|
||||
def create
|
||||
result = ::ScimClients::CreateService.new(user: User.current).call(scim_client_params)
|
||||
result.on_failure do
|
||||
@scim_client = result.result
|
||||
stream_form_component do |format|
|
||||
format.html { render :new }
|
||||
end
|
||||
end
|
||||
|
||||
result.on_success do
|
||||
flash[:notice] = t(:notice_successful_create)
|
||||
redirect_to edit_admin_scim_client_path(result.result, first_time_setup: true)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@scim_client = ScimClient.find(params[:id])
|
||||
result = ::ScimClients::UpdateService.new(user: User.current, model: @scim_client).call(scim_client_params)
|
||||
|
||||
result.on_failure do
|
||||
stream_form_component do |format|
|
||||
format.html { render :edit }
|
||||
end
|
||||
end
|
||||
|
||||
result.on_success do
|
||||
flash[:notice] = t(:notice_successful_update)
|
||||
redirect_to action: :index
|
||||
end
|
||||
end
|
||||
|
||||
def deletion_dialog
|
||||
respond_with_dialog ScimClients::DeleteScimClientDialogComponent.new(ScimClient.find(params[:id]))
|
||||
end
|
||||
|
||||
def destroy
|
||||
model = ScimClient.find(params[:id])
|
||||
result = ::ScimClients::DeleteService.new(user: User.current, model:).call
|
||||
|
||||
if result.success?
|
||||
flash[:notice] = I18n.t(:notice_successful_delete)
|
||||
else
|
||||
flash[:error] = result.errors.full_messages
|
||||
end
|
||||
|
||||
redirect_to action: :index
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scim_client_params
|
||||
params.expect(scim_client: %i[name auth_provider_id authentication_method jwt_sub])
|
||||
end
|
||||
|
||||
def first_time_setup(scim_client)
|
||||
return if params[:first_time_setup].blank?
|
||||
|
||||
case scim_client.authentication_method
|
||||
when "oauth2_token"
|
||||
if scim_client.access_tokens.empty?
|
||||
::ScimClients::GenerateStaticTokenService.new(scim_client).call
|
||||
@setup_token = true
|
||||
end
|
||||
when "oauth2_client"
|
||||
# Ensuring that the client secret can't infinitely be accessed by calling with ?first_time_setup=true long after
|
||||
# the initial setup (there is no other persisted marker showing us, that this is the first time)
|
||||
if scim_client.oauth_application.created_at > 1.minute.ago
|
||||
@setup_client_credentials = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def stream_form_component(&)
|
||||
update_via_turbo_stream(component: Admin::ScimClients::FormComponent.new(@scim_client))
|
||||
respond_with_turbo_streams(&)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,105 @@
|
||||
# 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 ScimClients
|
||||
class Form < ApplicationForm
|
||||
form do |client_form|
|
||||
client_form.text_field(
|
||||
name: :name,
|
||||
label: ScimClient.human_attribute_name(:name),
|
||||
required: true,
|
||||
caption: I18n.t("admin.scim_clients.form.name_description"),
|
||||
input_width: :large
|
||||
)
|
||||
|
||||
client_form.select_list(
|
||||
name: :auth_provider_id,
|
||||
label: ScimClient.human_attribute_name(:auth_provider_id),
|
||||
caption: I18n.t("admin.scim_clients.form.auth_provider_description"),
|
||||
input_width: :large,
|
||||
include_blank: false
|
||||
) do |select|
|
||||
AuthProvider.find_each do |provider|
|
||||
select.option(
|
||||
value: provider.id,
|
||||
label: provider.display_name
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
client_form.select_list(
|
||||
name: :authentication_method,
|
||||
label: ScimClient.human_attribute_name(:authentication_method),
|
||||
caption: I18n.t("admin.scim_clients.form.authentication_method_description_html").html_safe,
|
||||
input_width: :large,
|
||||
include_blank: false,
|
||||
disabled: model.persisted?,
|
||||
data: {
|
||||
action: "scim-clients--form-inputs#updateFormInputs",
|
||||
"scim-clients--form-inputs-target": "authenticationMethodInput"
|
||||
}
|
||||
) do |select|
|
||||
ScimClient.authentication_methods.each_key do |method|
|
||||
select.option(
|
||||
value: method,
|
||||
label: I18n.t("admin.scim_clients.authentication_methods.#{method}")
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
client_form.group(data: { "scim-clients--form-inputs-target": "jwtSubInputWrapper" }) do |group|
|
||||
group.text_field(
|
||||
name: :jwt_sub,
|
||||
label: ScimClient.human_attribute_name(:jwt_sub),
|
||||
required: true,
|
||||
caption: I18n.t("admin.scim_clients.form.jwt_sub_description_html", docs_url: "#").html_safe, # TODO: correct docs url
|
||||
input_width: :large
|
||||
)
|
||||
end
|
||||
|
||||
if show_client_id?
|
||||
client_form.html_content do
|
||||
render(Admin::ScimClients::ClientIdComponent.new(model))
|
||||
end
|
||||
end
|
||||
|
||||
client_form.submit(
|
||||
name: :submit,
|
||||
label: model.persisted? ? I18n.t(:button_save) : I18n.t(:button_create),
|
||||
scheme: :primary,
|
||||
data: { "scim-clients--form-inputs-target": "submitButton" }
|
||||
)
|
||||
end
|
||||
|
||||
def show_client_id?
|
||||
model.persisted? && model.authentication_method_oauth2_client?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -41,4 +41,23 @@ class ScimClient < ApplicationRecord
|
||||
oauth2_client: 1,
|
||||
oauth2_token: 2
|
||||
}, scopes: false, prefix: true
|
||||
|
||||
def access_tokens
|
||||
return Doorkeeper::AccessToken.none unless authentication_method_oauth2_token?
|
||||
|
||||
oauth_application.access_tokens
|
||||
end
|
||||
|
||||
def jwt_sub
|
||||
auth_provider_link&.external_id
|
||||
end
|
||||
|
||||
# This method is part of a nasty workaround for creating and updating SCIM clients:
|
||||
# To be able to validate the jwt_sub, the SetAttributesService must be able to effectively set the jwt_sub,
|
||||
# before it's validated by a contract. Afterwards the UpdateService must be able to persist the change. Since
|
||||
# user_auth_provider_links is a has_many association, there is no built-in memoization for values. So to make sure the
|
||||
# SetAttributesService, the Contract and the UpdateService all look at the same jwt_sub, we memoize the auth_provider_link here
|
||||
def auth_provider_link
|
||||
@auth_provider_link ||= service_account&.user_auth_provider_links&.first
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,24 +33,12 @@ class ScimClients::CreateService < BaseServices::Create
|
||||
super.tap do |service_result|
|
||||
self.model = service_result.result
|
||||
|
||||
update_service_account
|
||||
update_oauth_application(service_result)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_service_account
|
||||
service_account.name = params[:name]
|
||||
if model.authentication_method_sso?
|
||||
service_account.user_auth_provider_links.build(
|
||||
auth_provider_id: params[:auth_provider_id],
|
||||
external_id: params[:jwt_sub]
|
||||
)
|
||||
end
|
||||
service_account.save!
|
||||
end
|
||||
|
||||
def update_oauth_application(service_result)
|
||||
return if !model.authentication_method_oauth2_client? && !model.authentication_method_oauth2_token?
|
||||
|
||||
@@ -60,7 +48,7 @@ class ScimClients::CreateService < BaseServices::Create
|
||||
end
|
||||
|
||||
def service_account
|
||||
@service_account ||= model.build_service_account(admin: true)
|
||||
model.service_account
|
||||
end
|
||||
|
||||
def create_oauth_application
|
||||
@@ -69,6 +57,7 @@ class ScimClients::CreateService < BaseServices::Create
|
||||
.call(
|
||||
name: "#{model.name} (#{ScimClient.model_name.human})",
|
||||
redirect_uri: "urn:ietf:wg:oauth:2.0:oob",
|
||||
client_credentials_user_id: service_account.id,
|
||||
scopes: "scim_v2",
|
||||
confidential: true,
|
||||
integration: model,
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#++
|
||||
|
||||
class ScimClients::DeleteService < BaseServices::Delete
|
||||
def before_perform(_, call)
|
||||
def before_perform(call)
|
||||
# pre-loading service_account association before destroy to ensure it's available afterwards
|
||||
call.result.service_account
|
||||
call
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# 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 ScimClients::GenerateStaticTokenService < BaseServices::BaseCallable
|
||||
def initialize(scim_client)
|
||||
super()
|
||||
|
||||
@scim_client = scim_client
|
||||
end
|
||||
|
||||
def perform
|
||||
return ServiceResult.failure unless @scim_client.authentication_method_oauth2_token?
|
||||
|
||||
token = @scim_client.oauth_application.access_tokens.create(scopes: "scim_v2", expires_in:)
|
||||
if token.persisted?
|
||||
ServiceResult.success(result: token)
|
||||
else
|
||||
ServiceResult.failure(errors: token.errors)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expires_in
|
||||
(1.year.from_now - Time.zone.now).to_i
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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 ScimClients::RevokeStaticTokenService < BaseServices::BaseCallable
|
||||
def initialize(scim_client)
|
||||
super()
|
||||
|
||||
@scim_client = scim_client
|
||||
end
|
||||
|
||||
def perform(access_token)
|
||||
return ServiceResult.failure if access_token.application.integration != @scim_client
|
||||
|
||||
access_token.revoke unless access_token.revoked?
|
||||
|
||||
ServiceResult.success(result: access_token)
|
||||
end
|
||||
end
|
||||
@@ -34,6 +34,24 @@ module ScimClients
|
||||
|
||||
def set_attributes(params)
|
||||
super(params.except(:jwt_sub))
|
||||
update_service_account
|
||||
end
|
||||
|
||||
def update_service_account
|
||||
service_account.assign_attributes(params.slice(:name))
|
||||
|
||||
if model.authentication_method_sso?
|
||||
auth_provider_link.assign_attributes(params.slice(:auth_provider_id))
|
||||
auth_provider_link.external_id = params[:jwt_sub] if params.key?(:jwt_sub)
|
||||
end
|
||||
end
|
||||
|
||||
def service_account
|
||||
model.service_account || model.build_service_account(admin: true)
|
||||
end
|
||||
|
||||
def auth_provider_link
|
||||
@auth_provider_link ||= model.auth_provider_link || service_account.user_auth_provider_links.build
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,26 +31,9 @@
|
||||
class ScimClients::UpdateService < BaseServices::Update
|
||||
def after_perform(_)
|
||||
super.tap do |result|
|
||||
update_service_account(result.result)
|
||||
scim_client = result.result
|
||||
scim_client.service_account&.save!
|
||||
scim_client.auth_provider_link&.save!
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_service_account(scim_client)
|
||||
scim_client.service_account&.update!(params.slice(:name))
|
||||
|
||||
if model.authentication_method_sso?
|
||||
link = scim_client.service_account&.user_auth_provider_links&.find_or_initialize_by({})
|
||||
update_user_auth_provider_link(link)
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_auth_provider_link(link)
|
||||
return if link.nil?
|
||||
|
||||
link.auth_provider_id = params[:auth_provider_id] if params.key?(:auth_provider_id)
|
||||
link.external_id = params[:jwt_sub] if params.key?(:jwt_sub)
|
||||
link.save!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title t(:label_administration), ScimClient.model_name.human(count: 2), @scim_client.name %>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::PageHeader.new) do |header|
|
||||
header.with_title { @scim_client.name }
|
||||
header.with_description { t("admin.scim_clients.form.description_html", docs_url: "#") } # TODO: Deep link into documentation
|
||||
header.with_breadcrumbs(
|
||||
[{ href: admin_index_path, text: t(:label_administration) },
|
||||
{ href: admin_settings_authentication_path, text: t(:label_authentication) },
|
||||
{ href: admin_scim_clients_path, text: ScimClient.model_name.human(count: 2) },
|
||||
@scim_client.name]
|
||||
)
|
||||
|
||||
header.with_action_button(
|
||||
scheme: :danger,
|
||||
mobile_icon: :trash,
|
||||
mobile_label: t("button_delete"),
|
||||
aria: { label: t(".label_delete_scim_client") },
|
||||
tag: :a,
|
||||
href: deletion_dialog_admin_scim_client_path(@scim_client),
|
||||
data: { controller: "async-dialog" }
|
||||
) do |button|
|
||||
button.with_leading_visual_icon(icon: :trash)
|
||||
t("button_delete")
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render(Admin::ScimClients::FormComponent.new(@scim_client)) %>
|
||||
|
||||
<%= render(Admin::ScimClients::TokenListComponent.new(@scim_client)) if @scim_client.authentication_method_oauth2_token? %>
|
||||
|
||||
<% if @setup_token %>
|
||||
<%= render(Admin::ScimClients::CreatedTokenDialogComponent.new(@scim_client.access_tokens.first, data: { controller: "auto-show-dialog" })) %>
|
||||
<% elsif @setup_client_credentials %>
|
||||
<%= render(Admin::ScimClients::CreatedClientCredentialsDialogComponent.new(@scim_client, data: { controller: "auto-show-dialog" })) %>
|
||||
<% end %>
|
||||
@@ -0,0 +1,55 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title t(:label_administration), ScimClient.model_name.human(count: 2) %>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::PageHeader.new) do |header|
|
||||
header.with_title { ScimClient.model_name.human(count: 2) }
|
||||
header.with_description { t(".description") }
|
||||
header.with_breadcrumbs(
|
||||
[{ href: admin_index_path, text: t(:label_administration) },
|
||||
{ href: admin_settings_authentication_path, text: t(:label_authentication) },
|
||||
ScimClient.model_name.human(count: 2)]
|
||||
)
|
||||
end
|
||||
%>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::SubHeader.new) do |component|
|
||||
component.with_action_button(leading_icon: :plus,
|
||||
label: t(".label_create_button"),
|
||||
scheme: :primary,
|
||||
tag: :a,
|
||||
href: new_admin_scim_client_path) { ScimClient.model_name.human }
|
||||
end
|
||||
%>
|
||||
|
||||
|
||||
<%= render(Admin::ScimClients::TableComponent.new(rows: @scim_clients)) %>
|
||||
@@ -0,0 +1,45 @@
|
||||
<%#-- 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.
|
||||
|
||||
++#%>
|
||||
|
||||
<% html_title t(:label_administration), ScimClient.model_name.human(count: 2), t(".title") %>
|
||||
|
||||
<%=
|
||||
render(Primer::OpenProject::PageHeader.new) do |header|
|
||||
header.with_title { t(".title") }
|
||||
header.with_description { t("admin.scim_clients.form.description_html", docs_url: "#") } # TODO: Deep link into documentation
|
||||
header.with_breadcrumbs(
|
||||
[{ href: admin_index_path, text: t(:label_administration) },
|
||||
{ href: admin_settings_authentication_path, text: t(:label_authentication) },
|
||||
{ href: admin_scim_clients_path, text: ScimClient.model_name.human(count: 2) },
|
||||
t(".title")]
|
||||
)
|
||||
end
|
||||
%>
|
||||
|
||||
<%= render(Admin::ScimClients::FormComponent.new(@scim_client)) %>
|
||||
@@ -49,3 +49,6 @@ OpenProject::FeatureDecisions.add :calculated_value_project_attribute,
|
||||
|
||||
OpenProject::FeatureDecisions.add :block_note_editor,
|
||||
description: "Enables the block note editor for rich text fields where available."
|
||||
|
||||
OpenProject::FeatureDecisions.add :scim_api,
|
||||
description: "Enables SCIM API."
|
||||
|
||||
@@ -510,14 +510,6 @@ Redmine::MenuManager.map :admin_menu do |menu|
|
||||
caption: :"authentication.login_and_registration",
|
||||
parent: :authentication
|
||||
|
||||
menu.push :ldap_authentication,
|
||||
{ controller: "/ldap_auth_sources", action: "index" },
|
||||
if: ->(_) { User.current.admin? && !OpenProject::Configuration.disable_password_login? },
|
||||
parent: :authentication,
|
||||
caption: :label_ldap_auth_source_plural,
|
||||
html: { class: "server_authentication" },
|
||||
last: true
|
||||
|
||||
menu.push :oauth_applications,
|
||||
{ controller: "/oauth/applications", action: "index" },
|
||||
if: ->(_) { User.current.admin? },
|
||||
@@ -525,6 +517,19 @@ Redmine::MenuManager.map :admin_menu do |menu|
|
||||
caption: :"oauth.application.plural",
|
||||
html: { class: "oauth_applications" }
|
||||
|
||||
menu.push :ldap_authentication,
|
||||
{ controller: "/ldap_auth_sources", action: "index" },
|
||||
if: ->(_) { User.current.admin? && !OpenProject::Configuration.disable_password_login? },
|
||||
parent: :authentication,
|
||||
caption: :label_ldap_auth_source_plural,
|
||||
html: { class: "server_authentication" }
|
||||
|
||||
menu.push :scim_clients,
|
||||
{ controller: "/admin/scim_clients", action: "index" },
|
||||
if: ->(_) { User.current.admin? && OpenProject::FeatureDecisions.scim_api_active? },
|
||||
parent: :authentication,
|
||||
caption: ScimClient.model_name.human(count: 2)
|
||||
|
||||
menu.push :announcements,
|
||||
{ controller: "/announcements", action: "edit" },
|
||||
if: ->(_) { User.current.admin? },
|
||||
|
||||
+60
-3
@@ -119,6 +119,59 @@ en:
|
||||
explanation:
|
||||
text: "Individual actions of a user (e.g. updating a work package twice) are aggregated into a single action if their age difference is less than the specified timespan. They will be displayed as a single action within the application. This will also delay notifications by the same amount of time reducing the number of emails being sent and will also affect %{webhook_link} delay."
|
||||
link: "webhook"
|
||||
scim_clients:
|
||||
authentication_methods:
|
||||
sso: "JWT from identity provider"
|
||||
oauth2_client: "OAuth 2.0 client credentials"
|
||||
oauth2_token: "Static access token"
|
||||
created_client_credentials_dialog_component:
|
||||
title: "Client credentials created"
|
||||
heading: "Client credentials have been generated"
|
||||
one_time_hint: "This is the only time you will see the client secret. Make sure to copy it now."
|
||||
created_token_dialog_component:
|
||||
title: "Token created"
|
||||
heading: "An token has been generated"
|
||||
label_token: "Token"
|
||||
one_time_hint: "This is the only time you will see this token. Make sure to copy it now."
|
||||
delete_scim_client_dialog_component:
|
||||
title: "Delete SCIM client"
|
||||
heading: "Are you sure you want to delete this SCIM client?"
|
||||
description: "Users managed by this SCIM client can no longer be updated by it."
|
||||
edit:
|
||||
label_delete_scim_client: "Delete SCIM client"
|
||||
form:
|
||||
auth_provider_description: "This is the service that users added by the SCIM provider will use to authenticate in OpenProject."
|
||||
authentication_method_description_html: "This is how the SCIM client authenticates at OpenProject. Please ensure that OAuth tokens include the <code>scim_v2</code> scope."
|
||||
description_html: 'Please refer to our <a href="%{docs_url}">documentation on configuring SCIM clients</a> for more information on these configuration options.'
|
||||
jwt_sub_description_html: 'For example, for Keycloak, this is the UUID of the service account associated with the SCIM client. Consult <a href="%{docs_url}">our documentation</a> to learn how to find the subject claim for your use case.'
|
||||
name_description: "Choose a name that will help other admins better understand why this client was configured."
|
||||
index:
|
||||
description: "SCIM clients are able to interact with OpenProject SCIM server API to provision, update, and deprovision user accounts and groups."
|
||||
label_create_button: "Add SCIM client"
|
||||
new:
|
||||
title: "New SCIM client"
|
||||
revoke_static_token_dialog_component:
|
||||
confirm_button: "Revoke"
|
||||
title: "Revoke static token"
|
||||
heading: "Are you sure you want to revoke this token?"
|
||||
description: "The SCIM client that uses this token will no longer be able to access OpenProject's SCIM server API."
|
||||
table_component:
|
||||
blank_slate:
|
||||
title: "No SCIM clients configured yet"
|
||||
description: "Add clients to see them here"
|
||||
user_count: "Users"
|
||||
token_list_component:
|
||||
description: "The tokens you generate here can be passed by a SCIM client to access the OpenProject SCIM API."
|
||||
heading: "Tokens"
|
||||
label_add_token: "Token"
|
||||
label_aria_add_token: "Add token"
|
||||
token_table_component:
|
||||
blank_slate:
|
||||
title: "No tokens have been created yet"
|
||||
description: "You can create one now"
|
||||
expired: "Expired on %{date}"
|
||||
revoked: "Revoked on %{date}"
|
||||
title: "Access token table"
|
||||
|
||||
authentication:
|
||||
login_and_registration: "Login and registration"
|
||||
@@ -966,7 +1019,7 @@ en:
|
||||
attribute_name: "Attribute"
|
||||
help_text: "Help text"
|
||||
auth_provider:
|
||||
scim_clients: "SCIM Clients"
|
||||
scim_clients: "SCIM clients"
|
||||
capability:
|
||||
context: "Context"
|
||||
changeset:
|
||||
@@ -1130,6 +1183,10 @@ en:
|
||||
url: "URL"
|
||||
role:
|
||||
permissions: "Permissions"
|
||||
scim_client:
|
||||
auth_provider: "Authentication provider"
|
||||
authentication_method: "Authentication method"
|
||||
jwt_sub: "Subject claim"
|
||||
status:
|
||||
is_closed: "Work package closed"
|
||||
is_readonly: "Work package read-only"
|
||||
@@ -1660,8 +1717,8 @@ en:
|
||||
one: "Role"
|
||||
other: "Roles"
|
||||
scim_client:
|
||||
one: "SCIM Client"
|
||||
other: "SCIM Clients"
|
||||
one: "SCIM client"
|
||||
other: "SCIM clients"
|
||||
status: "Work package status"
|
||||
token/api:
|
||||
one: Access token
|
||||
|
||||
@@ -630,6 +630,18 @@ Rails.application.routes.draw do
|
||||
controller: "/admin/attachments/quarantined_attachments",
|
||||
only: %i[index destroy]
|
||||
|
||||
resources :scim_clients, only: %i[index edit new create update destroy] do
|
||||
member do
|
||||
get :deletion_dialog
|
||||
end
|
||||
|
||||
resources :static_tokens, only: %i[create destroy], controller: "/admin/scim_client_static_tokens" do
|
||||
member do
|
||||
get :deletion_dialog
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
resource :backups, controller: "/admin/backups", only: %i[show] do
|
||||
collection do
|
||||
get :reset_token
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* -- 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.
|
||||
* ++
|
||||
*/
|
||||
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
export default class FormInputsController extends Controller {
|
||||
static targets = [
|
||||
'jwtSubInputWrapper',
|
||||
'authenticationMethodInput',
|
||||
'submitButton',
|
||||
];
|
||||
|
||||
declare readonly jwtSubInputWrapperTarget:HTMLDivElement;
|
||||
declare readonly authenticationMethodInputTarget:HTMLInputElement;
|
||||
declare readonly submitButtonTarget:HTMLButtonElement;
|
||||
|
||||
connect() {
|
||||
this.updateFormInputs();
|
||||
}
|
||||
|
||||
updateFormInputs() {
|
||||
if (this.authenticationMethodInputTarget.value === 'sso') {
|
||||
this.showJwtSubInput();
|
||||
} else {
|
||||
this.hideJwtSubInput();
|
||||
}
|
||||
}
|
||||
|
||||
showJwtSubInput() {
|
||||
this.jwtSubInputWrapperTarget.classList.remove('d-none');
|
||||
}
|
||||
|
||||
hideJwtSubInput() {
|
||||
this.jwtSubInputWrapperTarget.classList.add('d-none');
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ module OpenProject
|
||||
:plugin_saml,
|
||||
:saml_providers_path,
|
||||
parent: :authentication,
|
||||
after: :oauth_applications,
|
||||
caption: ->(*) { I18n.t("saml.menu_title") },
|
||||
enterprise_feature: "sso_auth_providers"
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ module OpenProject::LdapGroups
|
||||
:plugin_ldap_groups,
|
||||
{ controller: "/ldap_groups/synchronized_groups", action: :index },
|
||||
parent: :authentication,
|
||||
last: true,
|
||||
after: :ldap_authentication,
|
||||
caption: ->(*) { I18n.t("ldap_groups.label_menu_item") },
|
||||
enterprise_feature: "ldap_groups"
|
||||
end
|
||||
|
||||
@@ -45,6 +45,7 @@ module OpenProject::OpenIDConnect
|
||||
:plugin_openid_connect,
|
||||
:openid_connect_providers_path,
|
||||
parent: :authentication,
|
||||
after: :oauth_applications,
|
||||
caption: ->(*) { I18n.t("openid_connect.menu_title") },
|
||||
enterprise_feature: "sso_auth_providers"
|
||||
end
|
||||
|
||||
@@ -33,5 +33,15 @@ FactoryBot.define do
|
||||
sequence(:name) { |n| "SCIM Client #{n}" }
|
||||
auth_provider factory: :oidc_provider
|
||||
authentication_method { :sso }
|
||||
|
||||
trait :oauth2_token do
|
||||
authentication_method { :oauth2_token }
|
||||
oauth_application
|
||||
end
|
||||
|
||||
trait :oauth2_client do
|
||||
authentication_method { :oauth2_client }
|
||||
oauth_application
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# 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 "Creating a SCIM client", :js, :selenium, driver: :firefox_de do
|
||||
shared_let(:admin) { create(:admin, preferences: { time_zone: "Etc/UTC" }) }
|
||||
shared_let(:oidc_provider) { create(:oidc_provider) }
|
||||
|
||||
current_user { admin }
|
||||
|
||||
it "can create a SCIM client authenticating through JWT", :aggregate_failures do
|
||||
visit new_admin_scim_client_path
|
||||
|
||||
expect(page).to be_axe_clean.within("#content")
|
||||
.skipping("link-in-text-block") # https://community.openproject.org/wp/65252
|
||||
|
||||
expect(page).to have_no_field("Subject claim")
|
||||
select "JWT from identity provider", from: "Authentication method"
|
||||
expect(page).to have_field("Subject claim")
|
||||
|
||||
select oidc_provider.display_name, from: "Authentication provider"
|
||||
|
||||
click_on("Create") # forgot to fill out form
|
||||
expect(page).to have_text("Name can't be blank")
|
||||
expect(page).to have_text("Subject claim can't be blank")
|
||||
|
||||
fill_in "Name", with: "My SCIM Client"
|
||||
fill_in "Subject claim", with: "123-abc-456-def"
|
||||
click_on("Create")
|
||||
wait_for { ScimClient.find_by(name: "My SCIM Client") }.not_to be_nil
|
||||
|
||||
created_client = ScimClient.find_by(name: "My SCIM Client")
|
||||
expect(page).to have_current_path(edit_admin_scim_client_path(created_client, first_time_setup: true))
|
||||
expect(created_client.auth_provider_id).to eq(oidc_provider.id)
|
||||
expect(created_client.authentication_method).to eq("sso")
|
||||
expect(created_client.auth_provider_link&.external_id).to eq("123-abc-456-def")
|
||||
end
|
||||
|
||||
it "can create a SCIM client authenticating through client credentials" do
|
||||
visit new_admin_scim_client_path
|
||||
|
||||
fill_in "Name", with: "My SCIM Client"
|
||||
select oidc_provider.display_name, from: "Authentication provider"
|
||||
select "OAuth 2.0 client credentials", from: "Authentication method"
|
||||
|
||||
click_on("Create")
|
||||
wait_for { ScimClient.find_by(name: "My SCIM Client") }.not_to be_nil
|
||||
|
||||
created_client = ScimClient.find_by(name: "My SCIM Client")
|
||||
expect(page).to have_current_path(edit_admin_scim_client_path(created_client, first_time_setup: true))
|
||||
|
||||
page.within_modal("Client credentials created") do
|
||||
expect(page).to have_field("Client ID", with: created_client.oauth_application.uid)
|
||||
expect(page).to have_field("Client secret", with: created_client.oauth_application.secret)
|
||||
end
|
||||
end
|
||||
|
||||
it "can create a SCIM client authenticating through a static access token" do
|
||||
visit new_admin_scim_client_path
|
||||
|
||||
fill_in "Name", with: "My SCIM Client"
|
||||
select oidc_provider.display_name, from: "Authentication provider"
|
||||
select "Static access token", from: "Authentication method"
|
||||
|
||||
click_on("Create")
|
||||
wait_for { ScimClient.find_by(name: "My SCIM Client") }.not_to be_nil
|
||||
|
||||
created_client = ScimClient.find_by(name: "My SCIM Client")
|
||||
expect(page).to have_current_path(edit_admin_scim_client_path(created_client, first_time_setup: true))
|
||||
|
||||
page.within_modal("Token created") do
|
||||
expect(page).to have_field("Token", with: created_client.oauth_application.access_tokens.last.token)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,75 @@
|
||||
# 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 "Listing SCIM clients", :js, :selenium, driver: :firefox_de do
|
||||
shared_let(:admin) { create(:admin, preferences: { time_zone: "Etc/UTC" }) }
|
||||
|
||||
current_user { admin }
|
||||
|
||||
context "when there are no SCIM clients" do
|
||||
it "renders a proper blank slate" do
|
||||
visit admin_scim_clients_path
|
||||
|
||||
expect(page).to be_axe_clean.within "#content"
|
||||
|
||||
within_test_selector("Admin::ScimClients::TableComponent") do
|
||||
expect(page).to have_content("No SCIM clients configured yet")
|
||||
expect(page).to have_content("Add clients to see them here")
|
||||
end
|
||||
|
||||
within(".SubHeader") do
|
||||
click_on "SCIM client"
|
||||
end
|
||||
|
||||
expect(page).to have_current_path(new_admin_scim_client_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are SCIM clients" do
|
||||
let!(:sso_client) { create(:scim_client) }
|
||||
|
||||
it "renders a proper clients table" do
|
||||
visit admin_scim_clients_path
|
||||
|
||||
expect(page).to be_axe_clean.within "#content"
|
||||
|
||||
within_test_selector("Admin::ScimClients::TableComponent") do
|
||||
within(".name") { expect(page).to have_content(sso_client.name) }
|
||||
within(".authentication_method") { expect(page).to have_content("JWT from identity provider") }
|
||||
|
||||
click_on(sso_client.name)
|
||||
end
|
||||
|
||||
expect(page).to have_current_path(edit_admin_scim_client_path(sso_client))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,166 @@
|
||||
# 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 "Updating a SCIM client", :js, :selenium, driver: :firefox_de do
|
||||
shared_let(:admin) { create(:admin, preferences: { time_zone: "Etc/UTC" }) }
|
||||
shared_let(:auth_provider) { create(:oidc_provider) }
|
||||
|
||||
let(:sso_scim_client) { create(:scim_client, auth_provider:) }
|
||||
let(:oauth_client_scim_client) { create(:scim_client, :oauth2_client, auth_provider:) }
|
||||
let(:token_scim_client) { create(:scim_client, :oauth2_token, auth_provider:) }
|
||||
|
||||
let!(:static_tokens) do
|
||||
application = token_scim_client.oauth_application
|
||||
[
|
||||
create(:oauth_access_token, application:, created_at: 2.weeks.ago, expires_in: 2.days.to_i),
|
||||
create(:oauth_access_token, application:, created_at: 1.week.ago, expires_in: 2.weeks.to_i)
|
||||
]
|
||||
end
|
||||
|
||||
current_user { admin }
|
||||
|
||||
it "can update a SCIM client authenticating through JWT", :aggregate_failures do
|
||||
visit edit_admin_scim_client_path(sso_scim_client)
|
||||
expect(page).to be_axe_clean.within("#content")
|
||||
.skipping("link-in-text-block") # https://community.openproject.org/wp/65252
|
||||
|
||||
expect(page.find_field("Authentication method", disabled: :all)).to be_disabled
|
||||
fill_in "Name", with: ""
|
||||
fill_in "Subject claim", with: ""
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_text("Name can't be blank")
|
||||
expect(page).to have_text("Subject claim can't be blank")
|
||||
|
||||
fill_in "Name", with: "New SSO name"
|
||||
fill_in "Subject claim", with: "new-claim"
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
within_test_selector("Admin::ScimClients::TableComponent") do
|
||||
expect(page).to have_text("New SSO name")
|
||||
end
|
||||
|
||||
visit edit_admin_scim_client_path(sso_scim_client)
|
||||
|
||||
within(".PageHeader") { click_on "Delete" }
|
||||
page.within_modal("Delete SCIM client") { click_on "Delete" }
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
expect(ScimClient.where(id: sso_scim_client.id)).to be_empty
|
||||
end
|
||||
|
||||
it "can update a SCIM client authenticating through client credentials", :aggregate_failures do
|
||||
visit edit_admin_scim_client_path(oauth_client_scim_client)
|
||||
expect(page).to be_axe_clean.within("#content")
|
||||
.skipping("link-in-text-block") # https://community.openproject.org/wp/65252
|
||||
|
||||
expect(page.find_field("Authentication method", disabled: :all)).to be_disabled
|
||||
fill_in "Name", with: ""
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_text("Name can't be blank")
|
||||
|
||||
fill_in "Name", with: "New client credentials name"
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
within_test_selector("Admin::ScimClients::TableComponent") do
|
||||
expect(page).to have_text("New client credentials name")
|
||||
end
|
||||
|
||||
visit edit_admin_scim_client_path(oauth_client_scim_client)
|
||||
|
||||
expect(page).to have_field("Client ID", with: oauth_client_scim_client.oauth_application.uid)
|
||||
expect(page).to have_no_field("Client secret")
|
||||
|
||||
within(".PageHeader") { click_on "Delete" }
|
||||
page.within_modal("Delete SCIM client") { click_on "Delete" }
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
expect(ScimClient.where(id: oauth_client_scim_client.id)).to be_empty
|
||||
end
|
||||
|
||||
it "can update a SCIM client authenticating through a static access token", :aggregate_failures do
|
||||
visit edit_admin_scim_client_path(token_scim_client)
|
||||
expect(page).to be_axe_clean.within("#content")
|
||||
.skipping("link-in-text-block") # https://community.openproject.org/wp/65252
|
||||
|
||||
expect(page.find_field("Authentication method", disabled: :all)).to be_disabled
|
||||
fill_in "Name", with: ""
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_text("Name can't be blank")
|
||||
|
||||
fill_in "Name", with: "New static token name"
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
within_test_selector("Admin::ScimClients::TableComponent") do
|
||||
expect(page).to have_text("New static token name")
|
||||
end
|
||||
|
||||
visit edit_admin_scim_client_path(token_scim_client)
|
||||
|
||||
within_test_selector("Admin::ScimClients::TokenTableComponent") do
|
||||
expect(page).to have_css(".created_at").twice
|
||||
expect(page).to have_css(".expires_at").twice
|
||||
expect(page).to have_text("Expired on").once
|
||||
expect(page).to have_no_text("Revoked on")
|
||||
|
||||
expect(page).to have_test_selector("op-scim-clients--revoke-token-button").once
|
||||
page.find_test_selector("op-scim-clients--revoke-token-button").click
|
||||
end
|
||||
|
||||
page.within_modal("Revoke static token") { click_on "Revoke" }
|
||||
|
||||
within_test_selector("Admin::ScimClients::TokenTableComponent") do
|
||||
expect(page).to have_text("Revoked on").once
|
||||
expect(page).to have_no_test_selector("op-scim-clients--revoke-token-button")
|
||||
end
|
||||
|
||||
page.find_test_selector("op-scim-clients--add-token-button").click
|
||||
within_modal("Token created") do
|
||||
expect(page).to have_field("Token", with: Doorkeeper::AccessToken.last.token)
|
||||
click_on("Close")
|
||||
end
|
||||
within_test_selector("Admin::ScimClients::TokenTableComponent") do
|
||||
expect(page).to have_css(".created_at").exactly(3).times
|
||||
expect(page).to have_css(".expires_at").exactly(3).times
|
||||
|
||||
expect(page).to have_test_selector("op-scim-clients--revoke-token-button").once
|
||||
end
|
||||
|
||||
within(".PageHeader") { click_on "Delete" }
|
||||
page.within_modal("Delete SCIM client") { click_on "Delete" }
|
||||
expect(page).to have_current_path(admin_scim_clients_path)
|
||||
expect(ScimClient.where(id: token_scim_client.id)).to be_empty
|
||||
end
|
||||
end
|
||||
@@ -1,82 +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"
|
||||
|
||||
RSpec.describe ScimClients::FormModel do
|
||||
describe ".from_client" do
|
||||
subject { described_class.from_client(client) }
|
||||
|
||||
let(:client) do
|
||||
create(
|
||||
:scim_client, service_account: create(:service_account, authentication_provider: auth_provider, external_id: "abc-def"),
|
||||
authentication_method: :sso,
|
||||
auth_provider:
|
||||
)
|
||||
end
|
||||
let(:auth_provider) { create(:oidc_provider) }
|
||||
|
||||
it "builds a proper FormModel", :aggregate_failures do
|
||||
expect(subject.name).to eq(client.name)
|
||||
expect(subject.auth_provider_id).to eq(auth_provider.id)
|
||||
expect(subject.authentication_method).to eq("sso")
|
||||
expect(subject.jwt_sub).to eq("abc-def")
|
||||
end
|
||||
|
||||
context "when the auth provider link is missing" do
|
||||
let(:client) do
|
||||
create :scim_client, service_account: create(:service_account),
|
||||
authentication_method: :sso,
|
||||
auth_provider:
|
||||
end
|
||||
|
||||
it "fills the auth_provider_id correctly" do
|
||||
expect(subject.auth_provider_id).to eq(auth_provider.id)
|
||||
end
|
||||
|
||||
it "leaves the jwt_sub blank" do
|
||||
expect(subject.jwt_sub).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".from_params" do
|
||||
subject { described_class.from_params(params) }
|
||||
|
||||
let(:params) { { name: "The Client", auth_provider_id: 42, authentication_method: :banana, jwt_sub: "a-sub" } }
|
||||
|
||||
it "builds a proper FormModel", :aggregate_failures do
|
||||
expect(subject.name).to eq("The Client")
|
||||
expect(subject.auth_provider_id).to eq(42)
|
||||
expect(subject.authentication_method).to eq("banana")
|
||||
expect(subject.jwt_sub).to eq("a-sub")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
# 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 ScimClients::GenerateStaticTokenService do
|
||||
subject(:service_result) { described_class.new(scim_client).call }
|
||||
|
||||
let(:scim_client) { create(:scim_client, :oauth2_token) }
|
||||
|
||||
it "returns a valid token", :aggregate_failures, :freeze_time do
|
||||
expect(service_result).to be_success
|
||||
|
||||
expect(service_result.result.expires_at).to eq(1.year.from_now)
|
||||
expect(service_result.result.includes_scope?("scim_v2")).to be_truthy # rubocop:disable RSpec/PredicateMatcher
|
||||
end
|
||||
|
||||
it "generates a token" do
|
||||
expect { subject }.to change(Doorkeeper::AccessToken, :count).by(1)
|
||||
end
|
||||
|
||||
context "when the SCIM client is authenticating through client credentials" do
|
||||
let(:scim_client) { create(:scim_client, :oauth2_client) }
|
||||
|
||||
it { is_expected.to be_failure }
|
||||
|
||||
it "does not generate a token" do
|
||||
expect { subject }.not_to change(Doorkeeper::AccessToken, :count)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the SCIM client is authenticating through IDP tokens" do
|
||||
let(:scim_client) { create(:scim_client) }
|
||||
|
||||
it { is_expected.to be_failure }
|
||||
|
||||
it "does not generate a token" do
|
||||
expect { subject }.not_to change(Doorkeeper::AccessToken, :count)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
# 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 ScimClients::RevokeStaticTokenService do
|
||||
subject(:service_result) { described_class.new(scim_client).call(token) }
|
||||
|
||||
let(:scim_client) { create(:scim_client, :oauth2_token) }
|
||||
let(:token) { scim_client.oauth_application.access_tokens.create!(expires_in: 60) }
|
||||
|
||||
it "revokes the token effective immediately", :aggregate_failures, :freeze_time do
|
||||
subject
|
||||
expect(token.reload).to be_revoked
|
||||
expect(token.revoked_at).to be_within(0.1).of(Time.zone.now)
|
||||
end
|
||||
|
||||
it { is_expected.to be_success }
|
||||
|
||||
context "when the token is already revoked", :freeze_time do
|
||||
let(:token) { scim_client.oauth_application.access_tokens.create!(expires_in: 60, revoked_at: 1.minute.ago) }
|
||||
|
||||
it { is_expected.to be_success }
|
||||
|
||||
it "doesn't set a new revoked_at" do
|
||||
subject
|
||||
expect(token.reload.revoked_at).to be_within(0.1).of(1.minute.ago)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the token belongs to a different SCIM client" do
|
||||
let(:token) { create(:scim_client, :oauth2_token).oauth_application.access_tokens.create!(expires_in: 60) }
|
||||
|
||||
it { is_expected.to be_failure }
|
||||
|
||||
it "does not revoke the token" do
|
||||
subject
|
||||
expect(token.reload).not_to be_revoked
|
||||
end
|
||||
end
|
||||
|
||||
context "when the token belongs to no SCIM client at all" do
|
||||
let(:token) { create(:oauth_application).access_tokens.create!(expires_in: 60) }
|
||||
|
||||
it { is_expected.to be_failure }
|
||||
|
||||
it "does not revoke the token" do
|
||||
subject
|
||||
expect(token.reload).not_to be_revoked
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -48,6 +48,10 @@ module TestSelectorFinders
|
||||
def have_test_selector(value, **)
|
||||
have_selector(test_selector(value), **)
|
||||
end
|
||||
|
||||
def have_no_test_selector(value, **)
|
||||
have_no_selector(test_selector(value), **)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
||||
Reference in New Issue
Block a user