OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/lib/api/v3/utilities/path_helper.rb

534 lines
14 KiB

#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 API
module V3
module Utilities
module PathHelper
include API::Utilities::UrlHelper
class ApiV3Path
extend API::Utilities::UrlHelper
def self.index(name, path = nil)
plural_name = name.to_s.pluralize
path ||= plural_name
define_singleton_method(plural_name) do
"#{root}/#{path}"
end
end
private_class_method :index
def self.show(name)
define_singleton_method(name) { |id| build_path(name, id) }
end
private_class_method :show
def self.create_form(name)
define_singleton_method(:"create_#{name}_form") { build_path(name, "form") }
end
private_class_method :create_form
def self.update_form(name)
define_singleton_method(:"#{name}_form") { |id| build_path(name, id, "form") }
end
private_class_method :update_form
def self.schema(name)
define_singleton_method(:"#{name}_schema") { build_path(name, "schema") }
end
private_class_method :schema
def self.build_path(name, *kwargs)
[root, name.to_s.pluralize, *kwargs].compact.join("/")
end
private_class_method :build_path
def self.resources(name,
except: [],
only: %i[index show create_form update_form schema])
(Array(only) - Array(except)).each do |method|
send(method, name)
end
end
private_class_method :resources
# Determining the root_path on every url we want to render is
# expensive. As the root_path will not change within a
# request, we can cache the first response on each request.
def self.root_path
RequestStore.store[:cached_root_path] ||= super
end
def self.root
"#{root_path}api/v3"
end
index :action
show :action
index :activity
show :activity
index :attachment
show :attachment
def self.attachment_content(id)
"#{root}/attachments/#{id}/content"
end
def self.attachments_by_post(id)
"#{post(id)}/attachments"
end
def self.attachments_by_work_package(id)
"#{work_package(id)}/attachments"
end
def self.attachments_by_help_text(id)
"#{help_text(id)}/attachments"
end
def self.attachments_by_wiki_page(id)
"#{wiki_page(id)}/attachments"
end
def self.prepare_new_attachment_upload
"#{root}/attachments/prepare"
end
index :attachment_upload
show :attachment_upload
def self.attachment_uploaded(attachment_id)
"#{root}/attachments/#{attachment_id}/uploaded"
end
def self.available_assignees(project_id)
"#{project(project_id)}/available_assignees"
end
def self.available_responsibles(project_id)
"#{project(project_id)}/available_responsibles"
end
def self.available_watchers(work_package_id)
"#{work_package(work_package_id)}/available_watchers"
end
def self.available_projects_on_edit(work_package_id)
"#{work_package(work_package_id)}/available_projects"
end
def self.available_projects_on_create(type_id)
if type_id.to_i.zero?
"#{work_packages}/available_projects"
else
"#{work_packages}/available_projects?for_type=#{type_id}"
end
end
def self.available_relation_candidates(work_package_id)
"#{work_package(work_package_id)}/available_relation_candidates"
end
index :capability
show :capability
def self.capabilities_contexts_global
"#{capabilities}/contexts/global"
end
index :backup
index :category
show :category
def self.categories_by_project(id)
"#{project(id)}/categories"
end
def self.configuration
"#{root}/configuration"
end
def self.create_project_work_package_form(project_id)
"#{work_packages_by_project(project_id)}/form"
end
def self.custom_action(id)
"#{root}/custom_actions/#{id}"
end
def self.custom_action_execute(id)
"#{custom_action(id)}/execute"
end
def self.custom_option(id)
"#{root}/custom_options/#{id}"
end
index :help_text
show :help_text
resources :grid
resources :membership
def self.memberships_available_projects
"#{memberships}/available_projects"
end
index :message
show :message
index :newses, :news
def self.news(id)
"#{newses}/#{id}"
end
index :notification
show :notification
def self.notification_bulk_read_ian
"#{notifications}/read_ian"
end
def self.notification_bulk_unread_ian
"#{notifications}/unread_ian"
end
def self.notification_read_ian(id)
"#{notification(id)}/read_ian"
end
def self.notification_unread_ian(id)
"#{notification(id)}/unread_ian"
end
index :placeholder_user
show :placeholder_user
index :post
show :post
index :principal
index :priorities
show :priority
class << self
alias :issue_priorities :priorities
alias :issue_priority :priority
end
resources :project
show :project_status
def self.projects_available_parents
"#{projects}/available_parent_projects"
end
def self.projects_schema
"#{projects}/schema"
end
def self.project_copy(id)
"#{project(id)}/copy"
end
def self.project_copy_form(id)
"#{project(id)}/copy/form"
end
resources :query
def self.query_default
"#{queries}/default"
end
def self.query_project_default(id)
"#{project(id)}/queries/default"
end
def self.query_star(id)
"#{query(id)}/star"
end
def self.query_unstar(id)
"#{query(id)}/unstar"
end
def self.query_order(id)
"#{query(id)}/order"
end
def self.query_column(name)
"#{queries}/columns/#{name}"
end
def self.query_group_by(name)
"#{queries}/group_bys/#{name}"
end
def self.query_sort_by(name, direction)
"#{queries}/sort_bys/#{name}-#{direction}"
end
def self.query_filter(name)
"#{queries}/filters/#{name}"
end
def self.query_filter_instance_schemas
"#{queries}/filter_instance_schemas"
end
def self.query_filter_instance_schema(id)
"#{queries}/filter_instance_schemas/#{id}"
end
def self.query_project_form(id)
"#{project(id)}/queries/form"
end
def self.query_project_filter_instance_schemas(id)
"#{project(id)}/queries/filter_instance_schemas"
end
def self.query_operator(name)
"#{queries}/operators/#{name}"
end
def self.query_project_schema(id)
"#{project(id)}/queries/schema"
end
def self.query_available_projects
"#{queries}/available_projects"
end
index :relations
show :relation
index :revision
show :revision
def self.render_markup(link: nil, plain: false)
format = if plain
OpenProject::TextFormatting::Formats.plain_format
else
OpenProject::TextFormatting::Formats.rich_format
end
path = "#{root}/render/#{format}"
path += "?context=#{link}" if link
path
end
index :role
show :role
def self.show_revision(project_id, identifier)
show_revision_project_repository_path(project_id, identifier)
end
def self.show_user(user_id)
user_path(user_id)
end
index :status
show :status
def self.string_object(value)
val = ::ERB::Util::url_encode(value)
"#{root}/string_objects?value=#{val}"
end
resources :time_entry
def self.time_entries_activity(activity_id)
"#{root}/time_entries/activities/#{activity_id}"
end
def self.time_entries_available_projects
"#{time_entries}/available_projects"
end
def self.time_entries_available_work_packages_on_create
"#{time_entries}/available_work_packages"
end
def self.time_entries_available_work_packages_on_edit(time_entry_id)
"#{time_entry(time_entry_id)}/available_work_packages"
end
index :type
show :type
def self.types_by_project(project_id)
"#{project(project_id)}/types"
end
resources :user
def self.user_lock(id)
"#{user(id)}/lock"
end
def self.user_preferences(id)
"#{user(id)}/preferences"
end
index :group
show :group
resources :version
index :view
show :view
def self.views_type(type)
"#{views}/#{type}"
end
def self.versions_available_projects
"#{versions}/available_projects"
end
def self.versions_by_project(project_id)
"#{project(project_id)}/versions"
end
def self.projects_by_version(version_id)
"#{version(version_id)}/projects"
end
def self.watcher(id, work_package_id)
"#{work_package_watchers(work_package_id)}/#{id}"
end
def self.wiki_page(id)
"#{root}/wiki_pages/#{id}"
end
resources :work_package, except: :schema
def self.work_package_schema(project_id, type_id)
"#{root}/work_packages/schemas/#{project_id}-#{type_id}"
end
def self.work_package_activities(id)
"#{work_package(id)}/activities"
end
def self.work_package_relations(id)
"#{work_package(id)}/relations"
end
def self.work_package_relation(id, work_package_id)
"#{work_package_relations(work_package_id)}/#{id}"
end
def self.work_package_available_relation_candidates(id)
"#{work_package(id)}/available_relation_candidates"
end
def self.work_package_revisions(id)
"#{work_package(id)}/revisions"
end
def self.work_package_schemas(*args)
path = "#{root}/work_packages/schemas"
if args.empty?
path
else
values = args.map do |project_id, type_id|
"#{project_id}-#{type_id}"
end
filter = [{ id: { operator: '=', values: values } }]
path + "?filters=#{CGI.escape(filter.to_s)}"
end
end
def self.work_package_sums_schema
"#{root}/work_packages/schemas/sums"
end
def self.work_package_watchers(id)
"#{work_package(id)}/watchers"
end
def self.work_packages_by_project(project_id)
"#{project(project_id)}/work_packages"
end
def self.path_for(path, filters: nil, sort_by: nil, group_by: nil, page_size: nil)
query_params = {
filters: filters&.to_json,
sortBy: sort_by&.to_json,
groupBy: group_by,
pageSize: page_size
}.reject { |_, v| v.blank? }
if query_params.any?
"#{send(path)}?#{query_params.to_query}"
else
send(path)
end
end
def self.url_for(path, arguments = nil)
duplicate_regexp = if OpenProject::Configuration.rails_relative_url_root
Regexp.new("#{OpenProject::Configuration.rails_relative_url_root}/$")
else
Regexp.new("/$")
end
root_url = OpenProject::StaticRouting::StaticUrlHelpers.new.root_url
root_url.gsub(duplicate_regexp, '') + send(path, arguments)
end
end
def api_v3_paths
::API::V3::Utilities::PathHelper::ApiV3Path
end
end
end
end
end