Merge pull request #7869 from opf/feature/bcf_api_projects
Feature/bcf api projects [ci skip]pull/7872/head
commit
b835a18851
@ -0,0 +1,80 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
class ParseResourceParamsService |
||||
attr_accessor :model, |
||||
:representer, |
||||
:current_user |
||||
|
||||
def initialize(user, model: nil, representer: nil) |
||||
self.current_user = user |
||||
self.model = model |
||||
|
||||
self.representer = if !representer && model |
||||
deduce_representer(model) |
||||
elsif representer |
||||
representer |
||||
else |
||||
raise 'Representer not defined' |
||||
end |
||||
end |
||||
|
||||
def call(request_body) |
||||
parsed = if request_body |
||||
parse_attributes(request_body) |
||||
else |
||||
{} |
||||
end |
||||
|
||||
ServiceResult.new(success: true, |
||||
result: parsed) |
||||
end |
||||
|
||||
private |
||||
|
||||
def deduce_representer(_model) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def parsing_representer |
||||
representer |
||||
.new(struct, current_user: current_user) |
||||
end |
||||
|
||||
def parse_attributes(request_body) |
||||
parsing_representer |
||||
.from_hash(request_body) |
||||
.to_h |
||||
end |
||||
|
||||
def struct |
||||
OpenStruct.new |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,43 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
class Formatter |
||||
def call(object, _env) |
||||
if object.is_a?(String) |
||||
object |
||||
elsif object.respond_to?(:to_json) |
||||
object.to_json |
||||
else |
||||
MultiJson.dump(object) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,244 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
# Root class of the API |
||||
# This is the place for all API wide configuration, helper methods, exceptions |
||||
# rescuing, mounting of differnet API versions etc. |
||||
|
||||
require 'open_project/authentication' |
||||
|
||||
module API |
||||
class RootAPI < Grape::API |
||||
include OpenProject::Authentication::Scope |
||||
extend API::Utilities::GrapeHelper |
||||
|
||||
content_type :json, 'application/json; charset=utf-8' |
||||
|
||||
use OpenProject::Authentication::Manager |
||||
|
||||
helpers API::Caching::Helpers |
||||
helpers do |
||||
def current_user |
||||
User.current |
||||
end |
||||
|
||||
def warden |
||||
env['warden'] |
||||
end |
||||
|
||||
## |
||||
# Helper to access only the declared |
||||
# params to avoid unvalidated access |
||||
# (e.g., in before blocks) |
||||
def declared_params |
||||
declared(params) |
||||
end |
||||
|
||||
def request_body |
||||
env['api.request.body'] |
||||
end |
||||
|
||||
def authenticate |
||||
warden.authenticate! scope: authentication_scope |
||||
|
||||
User.current = warden.user scope: authentication_scope |
||||
|
||||
if Setting.login_required? and not logged_in? |
||||
raise ::API::Errors::Unauthenticated |
||||
end |
||||
end |
||||
|
||||
def set_localization |
||||
SetLocalizationService.new(User.current, env['HTTP_ACCEPT_LANGUAGE']).call |
||||
end |
||||
|
||||
# Global helper to set allowed content_types |
||||
# This may be overriden when multipart is allowed (file uploads) |
||||
def allowed_content_types |
||||
%w(application/json application/hal+json) |
||||
end |
||||
|
||||
def enforce_content_type |
||||
# Content-Type is not present in GET |
||||
return if request.get? |
||||
|
||||
# Raise if missing header |
||||
content_type = request.content_type |
||||
error!('Missing content-type header', 406) unless content_type.present? |
||||
|
||||
# Allow JSON and JSON+HAL per default |
||||
# and anything that each endpoint may optionally add to that |
||||
if content_type.present? |
||||
allowed_content_types.each do |mime| |
||||
# Content-Type header looks like this (e.g.,) |
||||
# application/json;encoding=utf8 |
||||
return if content_type.start_with?(mime) |
||||
end |
||||
end |
||||
|
||||
bad_type = content_type.presence || I18n.t('api_v3.errors.missing_content_type') |
||||
message = I18n.t('api_v3.errors.invalid_content_type', |
||||
content_type: allowed_content_types.join(" "), |
||||
actual: bad_type) |
||||
|
||||
fail ::API::Errors::UnsupportedMediaType, message |
||||
end |
||||
|
||||
def logged_in? |
||||
# An admin SystemUser is anonymous but still a valid user to be logged in. |
||||
current_user && (current_user.admin? || !current_user.anonymous?) |
||||
end |
||||
|
||||
def authorize(permission, context: nil, global: false, user: current_user, &block) |
||||
auth_service = AuthorizationService.new(permission, |
||||
context: context, |
||||
global: global, |
||||
user: user) |
||||
|
||||
authorize_by_with_raise auth_service, &block |
||||
end |
||||
|
||||
def authorize_by_with_raise(callable) |
||||
is_authorized = callable.respond_to?(:call) ? callable.call : callable |
||||
|
||||
return true if is_authorized |
||||
|
||||
if block_given? |
||||
yield |
||||
else |
||||
raise API::Errors::Unauthorized |
||||
end |
||||
|
||||
false |
||||
end |
||||
|
||||
# checks whether the user has |
||||
# any of the provided permission in any of the provided |
||||
# projects |
||||
def authorize_any(permissions, projects: nil, global: false, user: current_user, &block) |
||||
raise ArgumentError if projects.nil? && !global |
||||
|
||||
projects = Array(projects) |
||||
|
||||
authorized = permissions.any? do |permission| |
||||
if global |
||||
authorize(permission, global: true, user: user) do |
||||
false |
||||
end |
||||
else |
||||
allowed_projects = Project.allowed_to(user, permission) |
||||
!(allowed_projects & projects).empty? |
||||
end |
||||
end |
||||
|
||||
authorize_by_with_raise(authorized, &block) |
||||
end |
||||
|
||||
def authorize_admin |
||||
authorize_by_with_raise(current_user.admin? && (current_user.active? || current_user.is_a?(SystemUser))) |
||||
end |
||||
|
||||
def authorize_logged_in |
||||
authorize_by_with_raise(current_user.logged? && current_user.active? || current_user.is_a?(SystemUser)) |
||||
end |
||||
|
||||
def raise_invalid_query_on_service_failure |
||||
service = yield |
||||
|
||||
if service.success? |
||||
service |
||||
else |
||||
api_errors = service.errors.full_messages.map do |message| |
||||
::API::Errors::InvalidQuery.new(message) |
||||
end |
||||
|
||||
raise ::API::Errors::MultipleErrors.create_if_many api_errors |
||||
end |
||||
end |
||||
end |
||||
|
||||
def self.auth_headers |
||||
lambda do |
||||
header = OpenProject::Authentication::WWWAuthenticate |
||||
.response_header(scope: authentication_scope, request_headers: env) |
||||
|
||||
{ 'WWW-Authenticate' => header } |
||||
end |
||||
end |
||||
|
||||
def self.error_representer(klass, content_type) |
||||
# Have the vars available in the instances via helpers. |
||||
helpers do |
||||
define_method(:error_representer, -> { klass }) |
||||
define_method(:error_content_type, -> { content_type }) |
||||
end |
||||
end |
||||
|
||||
def self.authentication_scope(sym) |
||||
# Have the scope available in the instances |
||||
# via a helper. |
||||
helpers do |
||||
define_method(:authentication_scope, -> { sym }) |
||||
end |
||||
end |
||||
|
||||
error_response ActiveRecord::RecordNotFound, ::API::Errors::NotFound, log: false |
||||
error_response ActiveRecord::StaleObjectError, ::API::Errors::Conflict, log: false |
||||
|
||||
error_response MultiJson::ParseError, ::API::Errors::ParseError |
||||
|
||||
error_response ::API::Errors::Unauthenticated, headers: auth_headers, log: false |
||||
error_response ::API::Errors::ErrorBase, rescue_subclasses: true, log: false |
||||
|
||||
# Handle grape validation errors |
||||
error_response ::Grape::Exceptions::ValidationErrors, ::API::Errors::BadRequest, log: false |
||||
|
||||
# Handle connection timeouts with appropriate payload |
||||
error_response ActiveRecord::ConnectionTimeoutError, |
||||
::API::Errors::InternalError, |
||||
log: ->(exception) do |
||||
payload = ::OpenProject::Logging::ThreadPoolContextBuilder.build! |
||||
::OpenProject.logger.error exception, reference: :APIv3, payload: payload |
||||
end |
||||
|
||||
# hide internal errors behind the same JSON response as all other errors |
||||
# only doing it in production to allow for easier debugging |
||||
if Rails.env.production? |
||||
error_response StandardError, ::API::Errors::InternalError, rescue_subclasses: true |
||||
end |
||||
|
||||
# run authentication before each request |
||||
after_validation do |
||||
authenticate |
||||
set_localization |
||||
enforce_content_type |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,172 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Bodied |
||||
def default_instance_generator(_model) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def default_params_modifier |
||||
->(params) do |
||||
params |
||||
end |
||||
end |
||||
|
||||
def initialize(model:, |
||||
api_name: model.name.demodulize, |
||||
instance_generator: default_instance_generator(model), |
||||
params_modifier: default_params_modifier, |
||||
process_service: nil, |
||||
parse_service: nil) |
||||
self.model = model |
||||
self.api_name = api_name |
||||
self.instance_generator = instance_generator |
||||
self.params_modifier = params_modifier |
||||
self.parse_representer = deduce_parse_representer |
||||
self.render_representer = deduce_render_representer |
||||
self.process_contract = deduce_process_contract |
||||
self.process_service = process_service || deduce_process_service |
||||
self.parse_service = parse_service || deduce_parse_service |
||||
end |
||||
|
||||
def mount |
||||
update = self |
||||
|
||||
-> do |
||||
params = update.parse(current_user, request_body) |
||||
|
||||
params = instance_exec(params, &update.params_modifier) |
||||
|
||||
call = update.process(current_user, |
||||
instance_exec(params, &update.instance_generator), |
||||
params) |
||||
|
||||
update.render(current_user, call) do |
||||
status update.success_status |
||||
end |
||||
end |
||||
end |
||||
|
||||
def parse(current_user, request_body) |
||||
parse_service |
||||
.new(current_user, |
||||
model: model, |
||||
representer: parse_representer) |
||||
.call(request_body) |
||||
.result |
||||
end |
||||
|
||||
def process(current_user, instance, params) |
||||
args = { user: current_user, |
||||
model: instance, |
||||
contract_class: process_contract } |
||||
|
||||
process_service |
||||
.new(args.compact) |
||||
.call(params) |
||||
end |
||||
|
||||
def render(current_user, call) |
||||
if success?(call) |
||||
yield |
||||
present_success(current_user, call) |
||||
else |
||||
present_error(call) |
||||
end |
||||
end |
||||
|
||||
def success_status |
||||
:ok |
||||
end |
||||
|
||||
attr_accessor :model, |
||||
:api_name, |
||||
:instance_generator, |
||||
:parse_representer, |
||||
:render_representer, |
||||
:params_modifier, |
||||
:process_contract, |
||||
:process_service, |
||||
:parse_service |
||||
|
||||
private |
||||
|
||||
def present_success(_current_user, _call) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def present_error(_call) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def success?(call) |
||||
call.success? |
||||
end |
||||
|
||||
def deduce_process_service |
||||
"::#{deduce_backend_namespace}::SetAttributesService".constantize |
||||
end |
||||
|
||||
def deduce_process_contract |
||||
"::#{deduce_backend_namespace}::#{update_or_create}Contract".constantize |
||||
end |
||||
|
||||
def deduce_parse_representer |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_parse_service |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_render_representer |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_api_namespace |
||||
api_name.pluralize |
||||
end |
||||
|
||||
def backend_name |
||||
model.name.demodulize |
||||
end |
||||
|
||||
def deduce_backend_namespace |
||||
backend_name.pluralize |
||||
end |
||||
|
||||
def update_or_create |
||||
raise NotImplementedError |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,50 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Create < Modify |
||||
def default_instance_generator(_model) |
||||
->(_params) do |
||||
end |
||||
end |
||||
|
||||
def success_status |
||||
:created |
||||
end |
||||
|
||||
private |
||||
|
||||
def update_or_create |
||||
"Create" |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,107 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Delete |
||||
def default_instance_generator(model) |
||||
->(_params) do |
||||
instance_variable_get("@#{model.name.demodulize.underscore}") |
||||
end |
||||
end |
||||
|
||||
def initialize(model:, |
||||
instance_generator: default_instance_generator(model), |
||||
process_service: nil) |
||||
self.model = model |
||||
self.instance_generator = instance_generator |
||||
self.process_service = process_service || deduce_process_service |
||||
end |
||||
|
||||
def mount |
||||
delete = self |
||||
|
||||
-> do |
||||
call = delete.process(current_user, |
||||
instance_exec(params, &delete.instance_generator)) |
||||
|
||||
delete.render(call) do |
||||
status delete.success_status |
||||
end |
||||
end |
||||
end |
||||
|
||||
def process(current_user, instance) |
||||
process_service |
||||
.new(user: current_user, |
||||
model: instance) |
||||
.call |
||||
end |
||||
|
||||
def render(call) |
||||
if success?(call) |
||||
yield |
||||
else |
||||
present_error(call) |
||||
end |
||||
end |
||||
|
||||
def success_status |
||||
204 |
||||
end |
||||
|
||||
attr_accessor :model, |
||||
:instance_generator, |
||||
:process_service |
||||
|
||||
private |
||||
|
||||
def present_error(call) |
||||
fail ::API::Errors::ErrorBase.create_and_merge_errors(call.errors) |
||||
end |
||||
|
||||
def success?(call) |
||||
call.success? |
||||
end |
||||
|
||||
def deduce_process_service |
||||
"::#{deduce_namespace}::DeleteService".constantize |
||||
end |
||||
|
||||
def deduce_namespace |
||||
demodulized_name.pluralize |
||||
end |
||||
|
||||
def demodulized_name |
||||
model.name.demodulize |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,74 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Index |
||||
include ::API::Utilities::PageSizeHelper |
||||
|
||||
def initialize(model:, |
||||
api_name: model.name.demodulize, |
||||
scope: nil, |
||||
render_representer: nil) |
||||
self.model = model_class(model) |
||||
self.scope = scope |
||||
self.api_name = api_name |
||||
self.render_representer = render_representer || deduce_render_representer |
||||
end |
||||
|
||||
def mount |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
attr_accessor :model, |
||||
:api_name, |
||||
:scope, |
||||
:render_representer |
||||
|
||||
private |
||||
|
||||
def deduce_render_representer |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_api_namespace |
||||
api_name.pluralize |
||||
end |
||||
|
||||
def model_class(scope) |
||||
if scope.is_a? Class |
||||
scope |
||||
else |
||||
scope.model |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,88 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Modify < Bodied |
||||
def default_instance_generator(model) |
||||
->(_params, _current_user) do |
||||
instance_variable_get("@#{model.name.demodulize.underscore}") |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def present_success(_current_user, _call) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def present_error(call) |
||||
errors = call.errors |
||||
errors = merge_dependent_errors call if errors.empty? |
||||
|
||||
api_errors = [::API::Errors::ErrorBase.create_and_merge_errors(errors)] |
||||
|
||||
fail ::API::Errors::MultipleErrors.create_if_many(api_errors) |
||||
end |
||||
|
||||
def merge_dependent_errors(call) |
||||
errors = ActiveModel::Errors.new call.result |
||||
|
||||
call.dependent_results.each do |dr| |
||||
dr.errors.keys.each do |field| |
||||
dr.errors.symbols_and_messages_for(field).each do |symbol, full_message, _| |
||||
errors.add :base, symbol, message: dependent_error_message(dr.result, full_message) |
||||
end |
||||
end |
||||
end |
||||
|
||||
errors |
||||
end |
||||
|
||||
def dependent_error_message(result, full_message) |
||||
I18n.t( |
||||
:error_in_dependent, |
||||
dependent_class: result.model_name.human, |
||||
related_id: result.id, |
||||
related_subject: result.name, |
||||
error: full_message |
||||
) |
||||
end |
||||
|
||||
def deduce_process_service |
||||
"::#{deduce_backend_namespace}::#{update_or_create}Service".constantize |
||||
end |
||||
|
||||
def deduce_process_contract |
||||
nil |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,86 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Show |
||||
def default_instance_generator(model) |
||||
->(_params) do |
||||
instance_variable_get("@#{model.name.demodulize.underscore}") |
||||
end |
||||
end |
||||
|
||||
def initialize(model:, |
||||
api_name: model.name.demodulize, |
||||
render_representer: nil, |
||||
instance_generator: default_instance_generator(model)) |
||||
|
||||
self.model = model |
||||
self.api_name = api_name |
||||
self.instance_generator = instance_generator |
||||
self.render_representer = render_representer || deduce_render_representer |
||||
end |
||||
|
||||
def mount |
||||
show = self |
||||
|
||||
-> do |
||||
show.render(instance_exec(params, &show.instance_generator)) |
||||
end |
||||
end |
||||
|
||||
def render(instance) |
||||
render_representer |
||||
.create(instance, |
||||
current_user: User.current, |
||||
embed_links: true) |
||||
end |
||||
|
||||
def self_path |
||||
api_name.underscore.pluralize |
||||
end |
||||
|
||||
attr_accessor :model, |
||||
:api_name, |
||||
:instance_generator, |
||||
:render_representer |
||||
|
||||
private |
||||
|
||||
def deduce_render_representer |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_api_namespace |
||||
api_name.pluralize |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,47 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module Utilities |
||||
module Endpoints |
||||
class Update < Modify |
||||
def default_instance_generator(model) |
||||
->(_params) do |
||||
instance_variable_get("@#{model.name.demodulize.underscore}") |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def update_or_create |
||||
"Update" |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,42 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API::V3 |
||||
class Parser |
||||
def call(object, _env) |
||||
MultiJson.load(object) |
||||
rescue MultiJson::ParseError => e |
||||
error = ::API::Errors::ParseError.new(details: e.message) |
||||
representer = ::API::V3::Errors::ErrorRepresenter.new(error) |
||||
|
||||
throw :error, status: 400, message: representer.to_json |
||||
end |
||||
end |
||||
end |
@ -1,170 +0,0 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Utilities |
||||
module Endpoints |
||||
class Bodied |
||||
def default_instance_generator(_model) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def default_params_modifier |
||||
->(params) do |
||||
params |
||||
end |
||||
end |
||||
|
||||
def initialize(model:, |
||||
api_name: model.name.demodulize, |
||||
instance_generator: default_instance_generator(model), |
||||
params_modifier: default_params_modifier, |
||||
process_service: nil, |
||||
parse_service: API::V3::ParseResourceParamsService) |
||||
self.model = model |
||||
self.api_name = api_name |
||||
self.instance_generator = instance_generator |
||||
self.params_modifier = params_modifier |
||||
self.parse_representer = deduce_parse_representer |
||||
self.render_representer = deduce_render_representer |
||||
self.process_contract = deduce_process_contract |
||||
self.process_service = process_service || deduce_process_service |
||||
self.parse_service = parse_service |
||||
end |
||||
|
||||
def mount |
||||
update = self |
||||
|
||||
-> do |
||||
params = update.parse(current_user, request_body) |
||||
|
||||
params = instance_exec(params, &update.params_modifier) |
||||
|
||||
call = update.process(current_user, |
||||
instance_exec(params, &update.instance_generator), |
||||
params) |
||||
|
||||
update.render(current_user, call) do |
||||
status update.success_status |
||||
end |
||||
end |
||||
end |
||||
|
||||
def parse(current_user, request_body) |
||||
parse_service |
||||
.new(current_user, |
||||
model: model, |
||||
representer: parse_representer) |
||||
.call(request_body) |
||||
.result |
||||
end |
||||
|
||||
def process(current_user, instance, params) |
||||
args = { user: current_user, |
||||
model: instance, |
||||
contract_class: process_contract } |
||||
|
||||
process_service |
||||
.new(args.compact) |
||||
.call(params) |
||||
end |
||||
|
||||
def render(current_user, call) |
||||
if success?(call) |
||||
yield |
||||
present_success(current_user, call) |
||||
else |
||||
present_error(call) |
||||
end |
||||
end |
||||
|
||||
def success_status |
||||
:ok |
||||
end |
||||
|
||||
attr_accessor :model, |
||||
:api_name, |
||||
:instance_generator, |
||||
:parse_representer, |
||||
:render_representer, |
||||
:params_modifier, |
||||
:process_contract, |
||||
:process_service, |
||||
:parse_service |
||||
|
||||
private |
||||
|
||||
def present_success(_current_user, _call) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def present_error(_call) |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def success?(call) |
||||
call.success? |
||||
end |
||||
|
||||
def deduce_process_service |
||||
"::#{decude_backend_namespace}::SetAttributesService".constantize |
||||
end |
||||
|
||||
def deduce_process_contract |
||||
"::#{decude_backend_namespace}::#{update_or_create}Contract".constantize |
||||
end |
||||
|
||||
def deduce_parse_representer |
||||
"::API::V3::#{deduce_api_namespace}::#{api_name}PayloadRepresenter".constantize |
||||
end |
||||
|
||||
def deduce_render_representer |
||||
raise NotImplementedError |
||||
end |
||||
|
||||
def deduce_api_namespace |
||||
api_name.pluralize |
||||
end |
||||
|
||||
def backend_name |
||||
model.name.demodulize |
||||
end |
||||
|
||||
def decude_backend_namespace |
||||
backend_name.pluralize |
||||
end |
||||
|
||||
def update_or_create |
||||
raise NotImplementedError |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -1,97 +0,0 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Utilities |
||||
module Endpoints |
||||
class Modify < Bodied |
||||
def default_instance_generator(model) |
||||
->(_params, _current_user) do |
||||
instance_variable_get("@#{model.name.demodulize.underscore}") |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def present_success(current_user, call) |
||||
render_representer |
||||
.create(call.result, |
||||
current_user: current_user, |
||||
embed_links: true) |
||||
end |
||||
|
||||
def present_error(call) |
||||
errors = call.errors |
||||
errors = merge_dependent_errors call if errors.empty? |
||||
|
||||
api_errors = [::API::Errors::ErrorBase.create_and_merge_errors(errors)] |
||||
|
||||
fail ::API::Errors::MultipleErrors.create_if_many(api_errors) |
||||
end |
||||
|
||||
def merge_dependent_errors(call) |
||||
errors = ActiveModel::Errors.new call.result |
||||
|
||||
call.dependent_results.each do |dr| |
||||
dr.errors.keys.each do |field| |
||||
dr.errors.symbols_and_messages_for(field).each do |symbol, full_message, _| |
||||
errors.add :base, symbol, message: dependent_error_message(dr.result, full_message) |
||||
end |
||||
end |
||||
end |
||||
|
||||
errors |
||||
end |
||||
|
||||
def dependent_error_message(result, full_message) |
||||
I18n.t( |
||||
:error_in_dependent, |
||||
dependent_class: result.model_name.human, |
||||
related_id: result.id, |
||||
related_subject: result.name, |
||||
error: full_message |
||||
) |
||||
end |
||||
|
||||
def deduce_process_service |
||||
"::#{decude_backend_namespace}::#{update_or_create}Service".constantize |
||||
end |
||||
|
||||
def deduce_render_representer |
||||
"::API::V3::#{deduce_api_namespace}::#{api_name}Representer".constantize |
||||
end |
||||
|
||||
def deduce_process_contract |
||||
nil |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,51 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Utilities |
||||
module Endpoints |
||||
module V3Deductions |
||||
private |
||||
|
||||
def deduce_parse_service |
||||
API::V3::ParseResourceParamsService |
||||
end |
||||
|
||||
def deduce_render_representer |
||||
"::API::V3::#{deduce_api_namespace}::#{api_name}Representer".constantize |
||||
end |
||||
|
||||
def deduce_parse_representer |
||||
"::API::V3::#{deduce_api_namespace}::#{api_name}PayloadRepresenter".constantize |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,44 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Utilities |
||||
module Endpoints |
||||
module V3PresentSingle |
||||
def present_success(current_user, call) |
||||
render_representer |
||||
.create(call.result, |
||||
current_user: current_user, |
||||
embed_links: true) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,56 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
# Root class of the API |
||||
# This is the place for all API wide configuration, helper methods, exceptions |
||||
# rescuing, mounting of different API versions etc. |
||||
|
||||
module Bcf::API |
||||
class Root < ::API::RootAPI |
||||
format :json |
||||
formatter :json, API::Formatter.new |
||||
|
||||
default_format :json |
||||
|
||||
error_representer ::Bcf::API::V2_1::Errors::ErrorRepresenter, :json |
||||
error_formatter :json, ::Bcf::API::ErrorFormatter::Json |
||||
|
||||
authentication_scope OpenProject::Authentication::Scope::BCF_V2_1 |
||||
|
||||
version '2.1', using: :path do |
||||
# /auth |
||||
mount ::Bcf::API::V2_1::AuthAPI |
||||
# /current-user |
||||
mount ::Bcf::API::V2_1::CurrentUserAPI |
||||
# /projects |
||||
mount ::Bcf::API::V2_1::ProjectsAPI |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,39 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class AuthAPI < ::API::OpenProjectAPI |
||||
resources :auth do |
||||
get do |
||||
::Bcf::API::V2_1::Auth::SingleRepresenter.new(nil) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,38 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class CurrentUserAPI < ::API::OpenProjectAPI |
||||
resources :'current-user' do |
||||
get &::Bcf::API::V2_1::Endpoints::Show.new(model: User, |
||||
instance_generator: ->(*) { current_user }).mount |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,57 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1::Endpoints |
||||
class Index < API::Utilities::Endpoints::Index |
||||
def mount |
||||
index = self |
||||
|
||||
-> do |
||||
collection = index.scope ? instance_exec(&index.scope) : index.model |
||||
|
||||
index.render(collection) |
||||
end |
||||
end |
||||
|
||||
def render(collection) |
||||
collection |
||||
.map do |instance| |
||||
render_representer |
||||
.new(instance) |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def deduce_render_representer |
||||
"::Bcf::API::V2_1::#{deduce_api_namespace}::SingleRepresenter".constantize |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,44 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1::Endpoints |
||||
class Show < API::Utilities::Endpoints::Show |
||||
def render(instance) |
||||
render_representer |
||||
.new(instance) |
||||
end |
||||
|
||||
private |
||||
|
||||
def deduce_render_representer |
||||
"::Bcf::API::V2_1::#{deduce_api_namespace}::SingleRepresenter".constantize |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,51 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1::Endpoints |
||||
class Update < API::Utilities::Endpoints::Update |
||||
def present_success(_current_user, call) |
||||
render_representer |
||||
.new(call.result) |
||||
end |
||||
|
||||
private |
||||
|
||||
def deduce_parse_service |
||||
Bcf::API::V2_1::ParseResourceParamsService |
||||
end |
||||
|
||||
def deduce_in_and_out_representer |
||||
"::Bcf::API::V2_1::#{deduce_api_namespace}::SingleRepresenter".constantize |
||||
end |
||||
|
||||
alias_method :deduce_parse_representer, :deduce_in_and_out_representer |
||||
alias_method :deduce_render_representer, :deduce_in_and_out_representer |
||||
end |
||||
end |
@ -0,0 +1,57 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class ProjectsAPI < ::API::OpenProjectAPI |
||||
resources :projects do |
||||
helpers do |
||||
def visible_projects |
||||
Project |
||||
.visible(current_user) |
||||
.has_module(:bcf) |
||||
end |
||||
end |
||||
|
||||
get &::Bcf::API::V2_1::Endpoints::Index.new(model: Project, |
||||
scope: -> { visible_projects }) |
||||
.mount |
||||
|
||||
route_param :id, regexp: /\A(\d+)\z/ do |
||||
after_validation do |
||||
@project = visible_projects |
||||
.find(params[:id]) |
||||
end |
||||
|
||||
get &::Bcf::API::V2_1::Endpoints::Show.new(model: Project).mount |
||||
put &::Bcf::API::V2_1::Endpoints::Update.new(model: Project).mount |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,43 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API |
||||
module ErrorFormatter |
||||
module Json |
||||
extend Grape::ErrorFormatter::Base |
||||
|
||||
class << self |
||||
def call(message, _backtrace, _options = {}, env = nil, _original_exception = nil) |
||||
present(message, env) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,56 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class Auth::SingleRepresenter < Roar::Decorator |
||||
include Representable::JSON |
||||
include OpenProject::StaticRouting::UrlHelpers |
||||
|
||||
property :oauth2_auth_url, |
||||
getter: ->(decorator:, **) { |
||||
"#{decorator.root_url}oauth/authorize" |
||||
} |
||||
|
||||
property :oauth2_token_url, |
||||
getter: ->(decorator:, **) { |
||||
"#{decorator.root_url}oauth/token" |
||||
} |
||||
|
||||
property :supported_oauth2_flows, |
||||
getter: ->(*) { |
||||
%w(authorization_code_grant client_credentials) |
||||
} |
||||
|
||||
property :http_basic_supported, |
||||
getter: ->(*) { |
||||
false |
||||
} |
||||
end |
||||
end |
@ -0,0 +1,39 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1::Errors |
||||
class ErrorRepresenter < Roar::Decorator |
||||
include Representable::JSON |
||||
|
||||
property :message, |
||||
getter: ->(*) { message }, |
||||
render_nil: true |
||||
end |
||||
end |
@ -0,0 +1,40 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class Projects::SingleRepresenter < Roar::Decorator |
||||
include Representable::JSON |
||||
|
||||
property :id, |
||||
as: :project_id |
||||
|
||||
property :name |
||||
end |
||||
end |
@ -0,0 +1,40 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf::API::V2_1 |
||||
class Users::SingleRepresenter < Roar::Decorator |
||||
include Representable::JSON |
||||
|
||||
property :mail, |
||||
as: :id |
||||
|
||||
property :name |
||||
end |
||||
end |
@ -0,0 +1,46 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Bcf |
||||
module API |
||||
module V2_1 |
||||
class ParseResourceParamsService < ::API::ParseResourceParamsService |
||||
private |
||||
|
||||
def deduce_representer(model) |
||||
"Bcf::API::V2_1::#{model.to_s.pluralize}::SingleRepresenter".constantize |
||||
end |
||||
|
||||
def parsing_representer |
||||
representer |
||||
.new(struct) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,148 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
describe 'authorization for BCF api', type: :feature, js: true do |
||||
let!(:user) { FactoryBot.create(:admin) } |
||||
let(:client_secret) { app.plaintext_secret } |
||||
let(:scope) { 'bcf_v2_1' } |
||||
let!(:project) { FactoryBot.create(:project) } |
||||
|
||||
def oauth_path(client_id) |
||||
"/oauth/authorize?response_type=code&client_id=#{client_id}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=#{scope}" |
||||
end |
||||
|
||||
before do |
||||
login_with user.login, 'adminADMIN!' |
||||
|
||||
visit oauth_applications_path |
||||
end |
||||
|
||||
it 'can create and later authorize and manage an OAuth application grant and then use the access token for the bcf api' do |
||||
# Initially empty |
||||
expect(page).to have_selector('.generic-table--empty-row', text: 'There is currently nothing to display') |
||||
|
||||
# Create application |
||||
find('.button', text: 'Add').click |
||||
fill_in 'application_name', with: 'My API application' |
||||
# Limit to bcf access |
||||
check scope |
||||
# Fill invalid redirect_uri |
||||
fill_in 'application_redirect_uri', with: "not a url!" |
||||
click_on 'Create' |
||||
|
||||
expect(page).to have_selector('.errorExplanation', text: 'Redirect URI must be an absolute URI.') |
||||
fill_in 'application_redirect_uri', with: "urn:ietf:wg:oauth:2.0:oob\nhttps://localhost/my/callback" |
||||
click_on 'Create' |
||||
|
||||
expect(page).to have_selector('.flash.notice', text: 'Successful creation.') |
||||
|
||||
expect(page).to have_selector('.attributes-key-value--key', |
||||
text: 'Client ID') |
||||
expect(page).to have_selector('.attributes-key-value--value', |
||||
text: "urn:ietf:wg:oauth:2.0:oob\nhttps://localhost/my/callback") |
||||
|
||||
# Should print secret on initial visit |
||||
expect(page).to have_selector('.attributes-key-value--key', text: 'Client secret') |
||||
client_secret = page.first('.attributes-key-value--value code').text |
||||
expect(client_secret).to match /\w+/ |
||||
|
||||
app = ::Doorkeeper::Application.first |
||||
|
||||
visit oauth_path app.uid |
||||
|
||||
# We get to the authorization screen |
||||
expect(page).to have_selector('h2', text: 'Authorize My API application') |
||||
|
||||
# With the correct scope printed |
||||
expect(page).to have_selector('li strong', text: I18n.t('oauth.scopes.bcf_v2_1')) |
||||
expect(page).to have_selector('li', text: I18n.t('oauth.scopes.bcf_v2_1_text')) |
||||
|
||||
# Authorize |
||||
find('input.button[value="Authorize"]').click |
||||
|
||||
# Expect auth token |
||||
code = find('#authorization_code').text |
||||
|
||||
# And also have a grant for this application |
||||
user.oauth_grants.reload |
||||
expect(user.oauth_grants.count).to eq 1 |
||||
expect(user.oauth_grants.first.application).to eq app |
||||
|
||||
parameters = { |
||||
client_id: app.uid, |
||||
client_secret: client_secret, |
||||
code: code, |
||||
grant_type: :authorization_code, |
||||
redirect_uri: app.redirect_uri.split.first |
||||
} |
||||
|
||||
session = ActionDispatch::Integration::Session.new(Rails.application) |
||||
response = session.post("/oauth/token", params: parameters) |
||||
expect(response).to eq 200 |
||||
body = JSON.parse(session.response.body) |
||||
|
||||
expect(body['access_token']).to be_present |
||||
expect(body['refresh_token']).to be_present |
||||
expect(body['scope']).to eq scope |
||||
|
||||
access_token = body['access_token'] |
||||
|
||||
# Should show that grant in my account |
||||
visit my_account_path |
||||
click_on 'Access token' |
||||
|
||||
expect(page).to have_selector("#oauth-application-grant-#{app.id}", text: app.name) |
||||
expect(page).to have_selector('td', text: app.name) |
||||
|
||||
# While being logged in, the api can be accessed with the session |
||||
visit("/api/bcf/2.1/projects/#{project.id}") |
||||
expect(page) |
||||
.to have_content(JSON.dump(project_id: project.id, name: project.name)) |
||||
|
||||
logout |
||||
|
||||
# While not being logged in and without a token, the api cannot be accessed |
||||
visit("/api/bcf/2.1/projects/#{project.id}") |
||||
expect(page) |
||||
.to have_content(JSON.dump(message: "The requested resource could not be found.")) |
||||
|
||||
## Without the access token, access is denied |
||||
api_session = ActionDispatch::Integration::Session.new(Rails.application) |
||||
response = api_session.get("/api/bcf/2.1/projects/#{project.id}") |
||||
expect(response).to eq 404 |
||||
|
||||
# With the access token, access is allowed |
||||
response = api_session.get("/api/bcf/2.1/projects/#{project.id}", |
||||
headers: { 'Authorization': "Bearer #{access_token}" }) |
||||
expect(response).to eq 200 |
||||
expect(api_session.response.body) |
||||
.to be_json_eql({ project_id: project.id, name: project.name }.to_json) |
||||
end |
||||
end |
@ -0,0 +1,74 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
require_relative '../shared_examples' |
||||
|
||||
describe Bcf::API::V2_1::Auth::SingleRepresenter, 'rendering' do |
||||
let(:instance) { described_class.new(nil) } |
||||
include OpenProject::StaticRouting::UrlHelpers |
||||
|
||||
subject { instance.to_json } |
||||
|
||||
describe 'attributes' do |
||||
before do |
||||
allow(OpenProject::Configuration) |
||||
.to receive(:rails_relative_url_root) |
||||
.and_return('/blubs') |
||||
end |
||||
|
||||
context 'oauth2_auth_url' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { "http://localhost:3000/blubs/oauth/authorize" } |
||||
let(:path) { 'oauth2_auth_url' } |
||||
end |
||||
end |
||||
|
||||
context 'oauth2_token_url' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { "http://localhost:3000/blubs/oauth/token" } |
||||
let(:path) { 'oauth2_token_url' } |
||||
end |
||||
end |
||||
|
||||
context 'http_basic_supported' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { false } |
||||
let(:path) { 'http_basic_supported' } |
||||
end |
||||
end |
||||
|
||||
context 'supported_oauth2_flows' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { %w(authorization_code_grant client_credentials) } |
||||
let(:path) { 'supported_oauth2_flows' } |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,55 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
require_relative '../shared_examples' |
||||
|
||||
describe Bcf::API::V2_1::Projects::SingleRepresenter, 'rendering' do |
||||
let(:project) { FactoryBot.build_stubbed(:project) } |
||||
|
||||
let(:instance) { described_class.new(project) } |
||||
|
||||
subject { instance.to_json } |
||||
|
||||
describe 'attributes' do |
||||
context 'project_id' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { project.id } |
||||
let(:path) { 'project_id' } |
||||
end |
||||
end |
||||
|
||||
context 'name' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { project.name } |
||||
let(:path) { 'name' } |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,8 @@ |
||||
shared_examples_for 'attribute' do |
||||
it 'reflects the project' do |
||||
expect(subject) |
||||
.to be_json_eql(value.to_json) |
||||
.at_path(path) |
||||
end |
||||
end |
||||
|
@ -0,0 +1,55 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
require_relative '../shared_examples' |
||||
|
||||
describe Bcf::API::V2_1::Users::SingleRepresenter, 'rendering' do |
||||
let(:user) { FactoryBot.build_stubbed(:user) } |
||||
|
||||
let(:instance) { described_class.new(user) } |
||||
|
||||
subject { instance.to_json } |
||||
|
||||
describe 'attributes' do |
||||
context 'id' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { user.mail } |
||||
let(:path) { 'id' } |
||||
end |
||||
end |
||||
|
||||
context 'name' do |
||||
it_behaves_like 'attribute' do |
||||
let(:value) { user.name } |
||||
let(:path) { 'name' } |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,62 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
require 'rack/test' |
||||
|
||||
require_relative './shared_responses' |
||||
|
||||
describe 'BCF 2.1 auth resource', type: :request, content_type: :json do |
||||
include Rack::Test::Methods |
||||
|
||||
let(:current_user) do |
||||
FactoryBot.create(:user) |
||||
end |
||||
|
||||
subject(:response) { last_response } |
||||
|
||||
describe 'GET /api/bcf/2.1/auth' do |
||||
let(:path) { "/api/bcf/2.1/auth" } |
||||
|
||||
before do |
||||
login_as(current_user) |
||||
get path |
||||
end |
||||
|
||||
it_behaves_like 'bcf api successful response' do |
||||
let(:expected_body) do |
||||
{ |
||||
"oauth2_auth_url": "http://localhost:3000/oauth/authorize", |
||||
"oauth2_token_url": "http://localhost:3000/oauth/token", |
||||
"http_basic_supported": false, |
||||
"supported_oauth2_flows": %w(authorization_code_grant client_credentials) |
||||
} |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,60 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
require 'rack/test' |
||||
|
||||
require_relative './shared_responses' |
||||
|
||||
describe 'BCF 2.1 current-user resource', type: :request, content_type: :json do |
||||
include Rack::Test::Methods |
||||
|
||||
let(:current_user) do |
||||
FactoryBot.create(:user) |
||||
end |
||||
|
||||
subject(:response) { last_response } |
||||
|
||||
describe 'GET /api/bcf/2.1/current-user' do |
||||
let(:path) { "/api/bcf/2.1/current-user" } |
||||
|
||||
before do |
||||
login_as(current_user) |
||||
get path |
||||
end |
||||
|
||||
it_behaves_like 'bcf api successful response' do |
||||
let(:expected_body) do |
||||
{ |
||||
id: current_user.mail, |
||||
name: current_user.name |
||||
} |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,156 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
require 'rack/test' |
||||
|
||||
require_relative './shared_responses' |
||||
|
||||
describe 'BCF 2.1 projects resource', type: :request, content_type: :json do |
||||
include Rack::Test::Methods |
||||
|
||||
let(:view_only_user) do |
||||
FactoryBot.create(:user, |
||||
member_in_project: project) |
||||
end |
||||
let(:edit_user) do |
||||
FactoryBot.create(:user, |
||||
member_in_project: project, |
||||
member_with_permissions: [:edit_project]) |
||||
end |
||||
let(:non_member_user) do |
||||
FactoryBot.create(:user) |
||||
end |
||||
|
||||
let(:project) { FactoryBot.create(:project, enabled_module_names: [:bcf]) } |
||||
subject(:response) { last_response } |
||||
|
||||
describe 'GET /api/bcf/2.1/projects/:project_id' do |
||||
let(:path) { "/api/bcf/2.1/projects/#{project.id}" } |
||||
let(:current_user) { view_only_user } |
||||
|
||||
before do |
||||
login_as(current_user) |
||||
get path |
||||
end |
||||
|
||||
it_behaves_like 'bcf api successful response' do |
||||
let(:expected_body) do |
||||
{ |
||||
project_id: project.id, |
||||
name: project.name |
||||
} |
||||
end |
||||
end |
||||
|
||||
context 'lacking permissions' do |
||||
let(:current_user) { non_member_user } |
||||
|
||||
it_behaves_like 'bcf api not found response' |
||||
end |
||||
end |
||||
|
||||
describe 'PUT /api/bcf/2.1/projects/:project_id' do |
||||
let(:path) { "/api/bcf/2.1/projects/#{project.id}" } |
||||
let(:current_user) { edit_user } |
||||
|
||||
let(:params) do |
||||
{ |
||||
name: 'new project name' |
||||
} |
||||
end |
||||
|
||||
before do |
||||
login_as(current_user) |
||||
put path, params.to_json |
||||
end |
||||
|
||||
it_behaves_like 'bcf api successful response' do |
||||
let(:expected_body) do |
||||
{ |
||||
project_id: project.id, |
||||
name: 'new project name' |
||||
} |
||||
end |
||||
end |
||||
|
||||
context 'lacking view permissions' do |
||||
let(:current_user) { non_member_user } |
||||
|
||||
it_behaves_like 'bcf api not found response' |
||||
end |
||||
|
||||
context 'lacking edit permissions' do |
||||
let(:current_user) { view_only_user } |
||||
|
||||
it_behaves_like 'bcf api not allowed response' |
||||
end |
||||
|
||||
context 'attempting to alter the id' do |
||||
let(:params) do |
||||
{ |
||||
project_id: 0 |
||||
} |
||||
end |
||||
|
||||
it_behaves_like 'bcf api unprocessable response' do |
||||
let(:message) { 'You must not write a read-only attribute.' } |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe 'GET /api/bcf/2.1/projects' do |
||||
let(:path) { "/api/bcf/2.1/projects" } |
||||
let(:current_user) { view_only_user } |
||||
let!(:invisible_project) { FactoryBot.create(:project, enabled_module_names: [:bcf]) } |
||||
let!(:non_bcf_project) do |
||||
FactoryBot.create(:project, enabled_module_names: [:work_packages]).tap do |p| |
||||
FactoryBot.create(:member, |
||||
project: p, |
||||
user: view_only_user, |
||||
roles: view_only_user.members.first.roles) |
||||
end |
||||
end |
||||
|
||||
before do |
||||
login_as(current_user) |
||||
get path |
||||
end |
||||
|
||||
it_behaves_like 'bcf api successful response' do |
||||
let(:expected_body) do |
||||
[ |
||||
{ |
||||
project_id: project.id, |
||||
name: project.name |
||||
} |
||||
] |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,107 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2019 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
shared_examples_for 'bcf api successful response' do |
||||
it 'responds 200 OK' do |
||||
expect(subject.status) |
||||
.to eql 200 |
||||
end |
||||
|
||||
it 'returns the project' do |
||||
expect(subject.body) |
||||
.to be_json_eql(expected_body.to_json) |
||||
end |
||||
|
||||
it 'is has a json content type header' do |
||||
expect(subject.headers['Content-Type']) |
||||
.to eql 'application/json; charset=utf-8' |
||||
end |
||||
end |
||||
|
||||
shared_examples_for 'bcf api not found response' do |
||||
it 'responds 404 NOT FOUND' do |
||||
expect(subject.status) |
||||
.to eql 404 |
||||
end |
||||
|
||||
it 'states a NOT FOUND message' do |
||||
expected = { |
||||
message: 'The requested resource could not be found.' |
||||
} |
||||
|
||||
expect(subject.body) |
||||
.to be_json_eql(expected.to_json) |
||||
end |
||||
|
||||
it 'is has a json content type header' do |
||||
expect(subject.headers['Content-Type']) |
||||
.to eql 'application/json; charset=utf-8' |
||||
end |
||||
end |
||||
|
||||
shared_examples_for 'bcf api not allowed response' do |
||||
it 'responds 403 NOT ALLOWED' do |
||||
expect(subject.status) |
||||
.to eql 403 |
||||
end |
||||
|
||||
it 'states a NOT ALLOWED message' do |
||||
expected = { |
||||
message: 'You are not authorized to access this resource.' |
||||
} |
||||
|
||||
expect(subject.body) |
||||
.to be_json_eql(expected.to_json) |
||||
end |
||||
|
||||
it 'is has a json content type header' do |
||||
expect(subject.headers['Content-Type']) |
||||
.to eql 'application/json; charset=utf-8' |
||||
end |
||||
end |
||||
|
||||
shared_examples_for 'bcf api unprocessable response' do |
||||
it 'responds 403 NOT ALLOWED' do |
||||
expect(subject.status) |
||||
.to eql 422 |
||||
end |
||||
|
||||
it 'states a reason message' do |
||||
expected = { |
||||
message: message |
||||
} |
||||
|
||||
expect(subject.body) |
||||
.to be_json_eql(expected.to_json) |
||||
end |
||||
|
||||
it 'is has a json content type header' do |
||||
expect(subject.headers['Content-Type']) |
||||
.to eql 'application/json; charset=utf-8' |
||||
end |
||||
end |
Loading…
Reference in new issue