Commit d7f58b19 authored by Bruno Nocera Zanette's avatar Bruno Nocera Zanette
Browse files

Merge branch 'implement-dspace6-auth' into 'master'

Implement DSpace6's new Endpoints and AuthMethod



See merge request !1
parents 7eb337da 879bfcd3
......@@ -10,4 +10,4 @@ gem 'activesupport'
group :development, :spec do
gem 'minitest', '~> 5.8.3'
gem 'rspec'
end
\ No newline at end of file
end
......@@ -5,6 +5,7 @@ require "faraday"
require "active_support/all"
require_relative "dspace/version"
require_relative "dspace/resources/schema_registry_resource"
require_relative "dspace/resources/community_resource"
require_relative "dspace/resources/collection_resource"
require_relative "dspace/resources/authentication_resource"
......@@ -18,6 +19,8 @@ require_relative "dspace/community"
require_relative "dspace/collection"
require_relative "dspace/item"
require_relative "dspace/metadata"
require_relative "dspace/schema"
require_relative "dspace/metadata_field"
require_relative "dspace/bitstream"
require_relative "dspace/policy"
require_relative "dspace/client"
......@@ -25,6 +28,10 @@ require_relative "dspace/client"
module Dspace
class NotAuthorizedError < StandardError; end
class NotFoundError < StandardError; end
class MethodNotAllowedError < StandardError; end
class UnsupportedMediaTypeError < StandardError; end
class ServerError < StandardError; end
class InvalidTokenError < StandardError; end
class InvalidCredentialsError < StandardError; end
......
......@@ -29,7 +29,7 @@ module Dspace
def to_h
{
id: @id,
uuid: @id,
name: @name,
type: @type,
link: @link,
......
......@@ -29,6 +29,24 @@ module Dspace
colls
end
def self.build_schemas(schemas=[])
return schemas unless schemas.is_a? Array
colls = []
schemas.each do |c|
colls << Dspace::Schema.new(c)
end
colls
end
def self.build_fields(fields=[])
return fields unless fields.is_a? Array
colls = []
fields.each do |c|
colls << Dspace::MetadataField.new(c)
end
colls
end
def self.build_bitstreams(bitstreams=[])
return bitstreams unless bitstreams.is_a? Array
colls = []
......
......@@ -2,7 +2,7 @@ module Dspace
class Client
DSPACE_API = 'https://demo.dspace.org'
attr_reader :access_token
attr_accessor :access_token
def initialize(options = {})
@access_token = options.with_indifferent_access[:access_token]
......@@ -12,6 +12,7 @@ module Dspace
def connection
Faraday.new(connection_options) do |req|
# req.response :logger
req.request :multipart
req.request :url_encoded
req.use(Faraday::Response::Logger, @logger) unless @logger.nil?
......@@ -26,7 +27,8 @@ module Dspace
collections: ::Dspace::Resources::CollectionResource,
communities: ::Dspace::Resources::CommunityResource,
status: ::Dspace::Resources::StatusResource,
authentication: ::Dspace::Resources::AuthenticationResource
authentication: ::Dspace::Resources::AuthenticationResource,
schema_registry: ::Dspace::Resources::SchemaRegistryResource
}
end
......@@ -42,36 +44,39 @@ module Dspace
resource(:status).test
end
def status
resource(:status).status
end
def login(email, password)
@access_token = resource(:authentication).login(email, password)
@access_token = resource(:authentication).login(email: email, password: password)
end
def logout
resource(:authentication).logout
@access_token = nil
(response = resource(:authentication).logout) && @access_token = nil
response
end
private
def resource(name)
if self.class.resources.keys.include?(name)
resources[name] ||= self.class.resources[name].new(connection: connection)
resources[name]
resources[name] = self.class.resources[name].new(connection: connection)
end
end
def connection_options
{
url: @dspace_api || DSPACE_API,
ssl: {
verify: false
},
headers: {
content_type: 'application/json',
accept: 'application/json',
'rest-dspace-token' => access_token.to_s,
user_agent: "dspace-rest-client #{Dspace::VERSION}"
}
url: @dspace_api || DSPACE_API,
ssl: {
verify: false
},
headers: {
content_type: 'application/json',
accept: 'application/json',
user_agent: "dspace-rest-client #{Dspace::VERSION}",
'Cookie' => @access_token.to_s
}
}
end
end
......
......@@ -15,7 +15,7 @@ module Dspace
@handle = args['handle']
@type = args['type']
@link = args['link']
@logo = args['logo']
@logo = Dspace::Bitstream.new(args['logo']) unless args['logo'].nil?
@license = args['license']
@copyright_text = args['copyrightText'] || args['copyright_text']
@introductory_text = args['introductoryText'] || args['introductory_text']
......@@ -31,7 +31,7 @@ module Dspace
def to_h
{
id: @id,
uuid: @id,
name: @name,
handle: @handle,
type: @type,
......
......@@ -13,7 +13,7 @@ module Dspace
@handle = args['handle']
@type = args['type']
@link = args['link']
@logo = args['logo']
@logo = Dspace::Bitstream.new(args['logo']) unless args['logo'].nil?
@parent_community = Dspace::Community.new(args['parentCommunity']) unless args['parentCommunity'].nil?
@copyright_text = args['copyrightText'] || args['copyright_text']
@introductory_text = args['introductoryText'] || args['introductory_text']
......@@ -27,7 +27,7 @@ module Dspace
def to_h
{
id: @id,
uuid: @id,
name: @name,
handle: @handle,
type: @type,
......
......@@ -27,7 +27,7 @@ module Dspace
def to_h
{
id: @id,
uuid: @id,
name: @name,
handle: @handle,
type: @type,
......
module Dspace
class MetadataField
include Dspace::Builders::HashBuilder
attr_accessor :name, :element, :qualifier, :description
attr_reader :id, :parent_schema, :expand
def initialize(args={})
@id = args['fieldId']
@name = args['name']
@parent_schema = args['parentSchema'] || args['parent_schema']
@element = args['element']
@qualifier = args['qualifier']
@description = args['description']
@expand = args['expand']
end
def to_h
{
fieldId: @id,
name: @name,
parentSchema: @parent_schema,
element: @element,
qualifier: @qualifier,
description: @description,
expand: @expand
}
end
end
end
......@@ -3,19 +3,26 @@ module Dspace
class AuthenticationResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler { |response| raise StandardError, "#{response}" }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :login, 'POST /rest/login' do
body { |email, password| JSON.generate({email: email, password: password}) }
handler(200, 201) { |response| access_token = response.body }
query_keys :email, :password
handler(200, 201) { |response| response['set-cookie'] }
end
action :logout, 'POST /rest/logout' do
body { |object| JSON.generate(object.to_h) }
handler(200, 201, 203, 204) { |response| true }
end
end
end
......
......@@ -3,13 +3,20 @@ module Dspace
class BitstreamResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler { |response| raise StandardError, "#{response}" }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :all, 'GET /rest/bitstreams' do
query_keys :expand, :limit, :offset
handler(200) do |response|
Dspace::Builders::ModelBuilder.build_items(JSON.parse(response.body))
Dspace::Builders::ModelBuilder.build_bitstreams(JSON.parse(response.body))
end
end
......
......@@ -3,8 +3,15 @@ module Dspace
class CollectionResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler { |response| raise StandardError, "#{response}" }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :all, 'GET /rest/collections' do
query_keys :expand, :limit, :offset
......
......@@ -3,8 +3,15 @@ module Dspace
class CommunityResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler { |response| raise StandardError, "#{response}" }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :all, 'GET /rest/communities' do
query_keys :expand, :limit, :offset
......
......@@ -3,8 +3,15 @@ module Dspace
class ItemResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler { |response| raise StandardError, "#{response}" }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :all, 'GET /rest/items' do
query_keys :expand, :limit, :offset
......@@ -64,7 +71,7 @@ module Dspace
end
action :update_metadata, 'PUT /rest/items/:id/metadata' do
body { |object| JSON.generate(object.to_h) }
body { |object| JSON.generate(Dspace::Builders::ModelBuilder.models2hash(object))}
handler(200, 201) { |response| true }
end
......
module Dspace
module Resources
class SchemaRegistryResource < ResourceKit::Resource
resources do
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
# GET /registries/schema
# => Return the list of metadata schemas in the registry
action :all,
'GET /rest/registries/schema' do
query_keys :expand
handler(200) do |response|
Dspace::Builders::ModelBuilder.build_schemas(JSON.parse(response.body))
end
end
# GET /registries/schema/{schema_prefix}
# => Returns the specified metadata schema
action :find_schema,
'GET /rest/registries/schema/:schema_prefix' do
query_keys :expand
handler(200) do |response|
Dspace::Schema.new(JSON.parse(response.body))
end
end
# POST /registries/schema/
# => Add a schema to the schema registry
action :create_schema,
'POST /rest/registries/schema' do
body { |object| JSON.generate(object.to_h) }
handler(200) do |response|
Dspace::Schema.new(JSON.parse(response.body))
end
end
# DELETE /registries/schema/{schema_id}
# => Delete the specified schema from the schema registry
action :delete_schema,
'DELETE /rest/registries/schema/:schema_id' do
handler(200) { |response| true }
end
# GET /registries/metadata-fields/{field_id}
# => Return the specified metadata field
action :find_metadata_field,
'GET /rest/registries/metadata-fields/:field_id' do
query_keys :expand
handler(200) do |response|
Dspace::MetadataField.new(JSON.parse(response.body))
end
end
# POST /registries/schema/{schema_prefix}/metadata-fields
# => Add a metadata field to the specified schema
action :create_metadata_field,
'POST /rest/registries/schema/:schema_prefix/metadata-fields' do
body { |object| JSON.generate(object.to_h) }
handler(200) do |response|
Dspace::MetadataField.new(JSON.parse(response.body))
end
end
# PUT /registries/metadata-fields/{field_id}
# => Update the specified metadata field
action :update_metadata_field,
'PUT /rest/registries/metadata-fields/:field_id' do
body { |object| JSON.generate(object.to_h) }
handler(200) { |response| true }
end
# DELETE /registries/metadata-fields/{field_id}
# => Delete the specified metadata field from the metadata field registry
action :delete_metadata_field,
'DELETE /rest/registries/metadata-fields/:field_id' do
handler(200) { |response| true }
end
# GET /registries/schema/{schema_prefix}/metadata-fields/{element}
# => Returns the metadata field within a schema with an unqualified element name
action :find_unqualified_element,
'GET /rest/registries/schema/:schema_prefix/metadata-fields/:element' do
query_keys :expand
handler(200) do |response|
Dspace::MetadataField.new(JSON.parse(response.body))
end
end
# GET /registries/schema/{schema_prefix}/metadata-fields/{element}/{qualifier}
# => Returns the metadata field within a schema with a qualified element name
action :find_qualified_element,
'GET /rest/registries/schema/:schema_prefix/metadata-fields/:element/:qualifier' do
handler(200) do |response|
Dspace::MetadataField.new(JSON.parse(response.body))
end
end
end
end
end
end
......@@ -3,7 +3,15 @@ module Dspace
class StatusResource < ResourceKit::Resource
resources do
default_handler { |response| raise StandardError, "#{response}" }
default_handler(400) { raise InvalidTokenError, 'Invalid access token.' }
default_handler(403) { raise InvalidCredentialsError, 'Wrong Dspace credentials.' }
default_handler(401) { raise NotAuthorizedError, 'This request requires authentication' }
default_handler(404) { raise NotFoundError, 'The specified object doesn\'t exist' }
default_handler(405) { raise MethodNotAllowedError, 'Wrong request method (GET,POST,PUT,DELETE) or wrong data format (JSON/XML)' }
default_handler(415) { raise UnsupportedMediaTypeError, 'Missing "Content-Type: application/json" or "Content-Type: application/xml" request header' }
default_handler(500) { raise ServerError, 'Likely a SQLException, IOException, more details in the logs' }
default_handler { |response| raise StandardError, "#{response.inspect}" }
action :test, 'GET /rest/test' do
handler(200, 201) { |response| true }
......
module Dspace
class Schema
include Dspace::Builders::HashBuilder
attr_accessor :namespace, :prefix, :expand
attr_reader :id, :fields
def initialize(args={})
@id = args['schemaID']
@namespace = args['namespace']
@prefix = args['prefix']
@expand = args['expand']
@fields = Dspace::Builders::ModelBuilder.build_fields(args['fields'])
end
def to_h
{
schemaID: @id,
namespace: @namespace,
prefix: @prefix,
expand: @expand,
fields: @fields
}
end
def add_field(name, element, description)
f = {}
f['name'] = name
f['element'] = element
f['description'] = description
@fields << Dspace::Field.new(f)
@fields
end
def reset_fields
@fields = []
end
end
end
module Dspace
VERSION = "2.2.7"
VERSION = "2.2.11"
end
require 'spec_helper'
RSpec.describe Dspace::Resources::SchemaRegistryResource, resource_kit: true do
subject(:resource) { Dspace::Resources::SchemaRegistryResource }
it 'get all schemas' do
expect(resource).to have_action(:all).that_handles(200).at_path('/rest/registries/schema').with_verb(:get) do |handled|
expect(handled).to all(be_kind_of(Dspace::Schema))
end
end
it 'find schema' do
expect(resource).to have_action(:find_schema).that_handles(200).at_path('/rest/registries/schema/:schema_prefix').with_verb(:get) do |handled|
expect(handled).to be_kind_of(Dspace::Schema)
end
end
it 'create a new schema' do
expect(resource).to have_action(:create_schema).that_handles(200).at_path('/rest/registries/schema').with_verb(:post) do |handled|
expect(handled).to be_kind_of(Dspace::Schema)
end
end
it 'delete schema' do
expect(resource).to have_action(:delete_schema).that_handles(200).at_path('/rest/registries/schema/:schema_id').with_verb(:delete) do |handled|
expect(handled).to eq(true)
end
end
it 'find metadata-field by id' do
expect(resource).to have_action(:find_metadata_field).that_handles(200).at_path('/rest/registries/metadata-fields/:field_id').with_verb(:get) do |handled|
expect(handled).to be_kind_of(Dspace::MetadataField)
end
end
it 'update a metadata-field' do
expect(resource).to have_action(:update_metadata_field).that_handles(200).at_path('/rest/registries/metadata-fields/:field_id').with_verb(:put) do |handled|
expect(handled).to eq(true)
end
end
it 'delete metadata-field' do
expect(resource).to have_action(:delete_metadata_field).that_handles(200).at_path('/rest/registries/metadata-fields/:field_id').with_verb(:delete) do |handled|
expect(handled).to eq(true)
end
end
context "with schema scope" do
it 'create a new metadata field' do
expect(resource).to have_action(:create_metadata_field).that_handles(200).at_path('/rest/registries/schema/:schema_prefix/metadata-fields').with_verb(:post) do |handled|
expect(handled).to be_kind_of(Dspace::MetadataField)
end
end
it 'find unqualified-element by element' do
expect(resource).to have_action(:find_unqualified_element).that_handles(200).at_path('/rest/registries/schema/:schema_prefix/metadata-fields/:element').with_verb(:get) do |handled|
expect(handled).to be_kind_of(Dspace::MetadataField)
end
end
it 'find qualified-element by element and qualifier' do
expect(resource).to have_action(:find_qualified_element).that_handles(200).at_path('/rest/registries/schema/:schema_prefix/metadata-fields/:element/:qualifier').with_verb(:get) do |handled|