Skip to content

Commit

Permalink
Merge pull request #15541 from opf/feature/53620/builtin-oauth-app-mo…
Browse files Browse the repository at this point in the history
…bile

Add OAuth application flow for builtin mobile app
  • Loading branch information
Kharonus authored Sep 13, 2024
2 parents f1cf558 + cf4c7c3 commit 28d8b74
Show file tree
Hide file tree
Showing 40 changed files with 1,141 additions and 212 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<%=
component_wrapper(data: { 'test-selector': "op-admin-oauth--application" }) do
flex_layout(align_items: :center, justify_content: :space_between) do |oauth_application_container|
oauth_application_container.with_column(flex_layout: true) do |application_information|
application_information.with_column(mr: 2) do
render(Primer::Beta::Link.new(href: oauth_application_path(@application), font_weight: :bold)) do
@application.name
end
end

application_information.with_column(mr: 2) do
render(Primer::Beta::Text.new(font_size: :small, color: :subtle)) do
if @application.builtin?
t("oauth.application.builtin")
else
t(:label_created_by, user: @application.owner)
end
end
end

unless @application.builtin?
application_information.with_column do
render(Primer::Beta::Label.new) do
@application.confidential? ? t("oauth.application.confidential") : t("oauth.application.non_confidential")
end
end
end
end

# Actions
oauth_application_container.with_column do
render(Primer::Alpha::ToggleSwitch.new(
src: toggle_oauth_application_path(@application),
csrf_token: form_authenticity_token,
checked: @application.enabled?,
data: {
'test-selector': "op-admin-oauth--application-enabled-toggle-switch"
}
))
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
Expand Down Expand Up @@ -30,50 +28,15 @@

module OAuth
module Applications
class RowComponent < ::RowComponent
property :confidential

def application
model
end

def name
link_to application.name, oauth_application_path(application)
end

def owner
link_to application.owner.name, user_path(application.owner)
end
class ApplicationRowComponent < ApplicationComponent
include ApplicationHelper
include OpPrimer::ComponentHelpers
include OpTurbo::Streamable

def confidential
if application.confidential?
helpers.op_icon "icon icon-checkmark"
end
end

def redirect_uri
urls = application.redirect_uri.split("\n")
safe_join urls, "<br/>".html_safe
end

def client_credentials
if user_id = application.client_credentials_user_id
helpers.link_to_user User.find(user_id)
else
"-"
end
end

def edit_link
link_to(
I18n.t(:button_edit),
edit_oauth_application_path(application),
class: "oauth-application--edit-link icon icon-edit"
)
end
def initialize(application:)
@application = application

def button_links
[edit_link, helpers.delete_link(oauth_application_path(application))]
super
end
end
end
Expand Down
55 changes: 55 additions & 0 deletions app/components/oauth/applications/index_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<%=
component_wrapper do
flex_layout do |index_container|
if OpenProject::FeatureDecisions.built_in_oauth_applications_active?
index_container.with_row do
render(border_box_container(mb: 4, data: {
'test-selector': "op-admin-oauth--built-in-applications"
})) do |component|
component.with_header(font_weight: :bold) do
render(Primer::Beta::Text.new) do
t("oauth.header.builtin_applications")
end
end

if @built_in_applications.empty?
component.with_row do
render(Primer::Beta::Text.new(data: {
'test-selector': "op-admin-oauth--built-in-applications-placeholder"
})) do
t("oauth.empty_application_lists")
end
end
end

@built_in_applications.each do |application|
component.with_row { render(OAuth::Applications::ApplicationRowComponent.new(application:)) }
end
end
end
end

index_container.with_row do
render(border_box_container(mb: 4)) do |component|
component.with_header(font_weight: :bold) do
render(Primer::Beta::Text.new) do
t("oauth.header.other_applications")
end
end

if @other_applications.empty?
component.with_row do
render(Primer::Beta::Text.new(data: { 'test-selector': "op-admin-oauth--applications-placeholder" })) do
t("oauth.empty_application_lists")
end
end
end

@other_applications.each do |application|
component.with_row { render(OAuth::Applications::ApplicationRowComponent.new(application:)) }
end
end
end
end
end
%>
44 changes: 44 additions & 0 deletions app/components/oauth/applications/index_component.rb
Original file line number Diff line number Diff line change
@@ -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.
#++

module OAuth
module Applications
class IndexComponent < ApplicationComponent
include ApplicationHelper
include OpPrimer::ComponentHelpers
include OpTurbo::Streamable

def initialize(oauth_applications:)
@built_in_applications = oauth_applications.select(&:builtin?)
@other_applications = oauth_applications.reject(&:builtin?)

super
end
end
end
end
50 changes: 26 additions & 24 deletions app/components/oauth/show_page_header_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,33 @@ See COPYRIGHT and LICENSE files for more details.
header.with_title { h(@application.name) }
header.with_breadcrumbs(breadcrumb_items)

header.with_action_button(tag: :a,
mobile_icon: :pencil,
mobile_label: t(:button_edit),
size: :medium,
href: edit_oauth_application_path(@application),
aria: { label: I18n.t(:button_edit) },
title: I18n.t(:button_edit)) do |button|
button.with_leading_visual_icon(icon: :pencil)
t(:button_edit)
end
unless @application.builtin?
header.with_action_button(tag: :a,
mobile_icon: :pencil,
mobile_label: t(:button_edit),
size: :medium,
href: edit_oauth_application_path(@application),
aria: { label: I18n.t(:button_edit) },
title: I18n.t(:button_edit)) do |button|
button.with_leading_visual_icon(icon: :pencil)
t(:button_edit)
end

header.with_action_button(tag: :a,
scheme: :danger,
mobile_icon: :trash,
mobile_label: t(:button_delete),
size: :medium,
href: oauth_application_path(@application),
aria: { label: I18n.t(:button_delete) },
data: {
confirm: I18n.t(:text_are_you_sure),
method: :delete
},
title: I18n.t(:button_delete)) do |button|
button.with_leading_visual_icon(icon: :trash)
t(:button_delete)
header.with_action_button(tag: :a,
scheme: :danger,
mobile_icon: :trash,
mobile_label: t(:button_delete),
size: :medium,
href: oauth_application_path(@application),
aria: { label: I18n.t(:button_delete) },
data: {
confirm: I18n.t(:text_are_you_sure),
method: :delete
},
title: I18n.t(:button_delete)) do |button|
button.with_leading_visual_icon(icon: :trash)
t(:button_delete)
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
# Copyright (C) 2012-2024 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.
Expand Down Expand Up @@ -30,46 +28,45 @@

module OAuth
module Applications
class TableComponent < ::TableComponent
class << self
def row_class
::OAuth::Applications::RowComponent
end
class BaseContract < ::ModelContract
def self.model
::Doorkeeper::Application
end

def initial_sort
%i[id asc]
end
validate :validate_client_credential_user
validate :validate_integration
validate :validate_admin_only

def sortable?
false
end
attribute :enabled
attribute :name
attribute :redirect_uri
attribute :confidential
attribute :owner_id
attribute :owner_type
attribute :scopes
attribute :client_credentials_user_id
attribute :integration_id
attribute :integration_type

def columns
headers.map(&:first)
end
private

def inline_create_link
link_to new_oauth_application_path,
aria: { label: t("oauth.application.new") },
class: "wp-inline-create--add-link",
title: t("oauth.application.new") do
helpers.op_icon("icon icon-add")
end
def validate_admin_only
errors.add :base, :error_unauthorized unless user.admin?
end

def empty_row_message
I18n.t :no_results_title_text
def validate_integration
both = model.integration_id.present? && model.integration_type.present?
none = model.integration_id.nil? && model.integration_type.nil?

errors.add :integration, :invalid unless both || none
end

def headers
[
["name", { caption: ::Doorkeeper::Application.human_attribute_name(:name) }],
["owner", { caption: ::Doorkeeper::Application.human_attribute_name(:owner) }],
["client_credentials", { caption: I18n.t("oauth.client_credentials") }],
["redirect_uri", { caption: ::Doorkeeper::Application.human_attribute_name(:redirect_uri) }],
["confidential", { caption: ::Doorkeeper::Application.human_attribute_name(:confidential) }]
]
def validate_client_credential_user
return if model.client_credentials_user_id.blank?

unless User.exists?(id: model.client_credentials_user_id)
errors.add :client_credentials_user_id, :invalid
end
end
end
end
Expand Down
Loading

0 comments on commit 28d8b74

Please sign in to comment.