diff --git a/lib/api/v3/attachments/attachment_model.rb b/lib/api/v3/attachments/attachment_model.rb new file mode 100644 index 0000000000..9b5d8c5b15 --- /dev/null +++ b/lib/api/v3/attachments/attachment_model.rb @@ -0,0 +1,47 @@ +#-- encoding: UTF-8 +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2014 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-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +require 'reform' +require 'reform/form/coercion' + +module API + module V3 + module Attachments + class AttachmentModel < Reform::Form + include Coercion + + property :filename, type: String + property :disk_filename, type: String + property :description, type: String + property :content_type, type: String + property :digest, type: String + end + end + end +end diff --git a/lib/api/v3/attachments/attachment_representer.rb b/lib/api/v3/attachments/attachment_representer.rb new file mode 100644 index 0000000000..2961ac928e --- /dev/null +++ b/lib/api/v3/attachments/attachment_representer.rb @@ -0,0 +1,75 @@ +#-- encoding: UTF-8 +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2014 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-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +require 'roar/decorator' +require 'roar/representer/json/hal' + +module API + module V3 + module Attachments + class AttachmentRepresenter < Roar::Decorator + include Roar::Representer::JSON::HAL + include Roar::Representer::Feature::Hypermedia + include OpenProject::StaticRouting::UrlHelpers + + self.as_strategy = API::Utilities::CamelCasingStrategy.new + + property :_type, exec_context: :decorator + + link :self do + { href: "#{root_url}api/v3/attachments/#{represented.model.id}", title: "#{represented.model.filename}" } + end + + link :work_package do + work_package = represented.model.container + { href: "#{root_url}api/v3/work_packages/#{work_package.id}", title: "#{work_package.subject}" } unless work_package.nil? + end + + link :author do + author = represented.model.author + { href: "#{root_url}api/v3/users/#{author.id}", title: "#{author.name} - #{author.login}" } unless author.nil? + end + + property :id, getter: -> (*) { model.id }, render_nil: true + property :filename, as: :fileName, render_nil: true + property :disk_filename, as: :diskFileName, render_nil: true + property :description, render_nil: true + property :file_size, getter: -> (*) { model.filesize }, render_nil: true + property :content_type, getter: -> (*) { model.content_type }, render_nil: true + property :digest, render_nil: true + property :downloads, getter: -> (*) { model.downloads }, render_nil: true + property :created_at, getter: -> (*) { model.created_on.utc.iso8601 }, render_nil: true + + def _type + 'Attachment' + end + end + end + end +end diff --git a/lib/api/v3/attachments/attachments_api.rb b/lib/api/v3/attachments/attachments_api.rb new file mode 100644 index 0000000000..64cc11145c --- /dev/null +++ b/lib/api/v3/attachments/attachments_api.rb @@ -0,0 +1,30 @@ +module API + module V3 + module Attachments + class AttachmentsAPI < Grape::API + + resources :attachments do + + params do + requires :id, desc: 'Attachment id' + end + namespace ':id' do + + before do + @attachment = Attachment.find(params[:id]) + model = ::API::V3::Attachments::AttachmentModel.new(@attachment) + @representer = ::API::V3::Attachments::AttachmentRepresenter.new(model) + end + + get do + @representer.to_json + end + + end + + end + + end + end + end +end diff --git a/lib/api/v3/root.rb b/lib/api/v3/root.rb index 7c90637dae..20c420eb95 100644 --- a/lib/api/v3/root.rb +++ b/lib/api/v3/root.rb @@ -38,6 +38,7 @@ module API mount API::V3::WorkPackages::WorkPackagesAPI mount API::V3::Queries::QueriesAPI + mount API::V3::Attachments::AttachmentsAPI end end end diff --git a/spec/api/representers/attachment_representer_spec.rb b/spec/api/representers/attachment_representer_spec.rb new file mode 100644 index 0000000000..80f43373a1 --- /dev/null +++ b/spec/api/representers/attachment_representer_spec.rb @@ -0,0 +1,70 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2014 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-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe ::API::V3::Attachments::AttachmentRepresenter do + let(:attachment) { FactoryGirl.create(:attachment) } + let(:model) { ::API::V3::Attachments::AttachmentModel.new(attachment) } + let(:representer) { ::API::V3::Attachments::AttachmentRepresenter.new(model) } + + context 'generation' do + subject(:generated) { representer.to_json } + + it { should include_json('Attachment'.to_json).at_path('_type') } + + describe 'attachment' do + it { should have_json_path('id') } + it { should have_json_path('fileName') } + it { should have_json_path('diskFileName') } + it { should have_json_path('description') } + it { should have_json_path('fileSize') } + it { should have_json_path('contentType') } + it { should have_json_path('digest') } + it { should have_json_path('downloads') } + it { should have_json_path('createdAt') } + end + + describe '_links' do + it { should have_json_type(Object).at_path('_links') } + + it 'should link to self' do + expect(subject).to have_json_path('_links/self/href') + end + + it 'should link to a work package' do + expect(subject).to have_json_path('_links/work_package/href') + end + + it 'should link to an author' do + expect(subject).to have_json_path('_links/author/href') + end + end + + end +end