1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

Merge pull request #403 from oceanprotocol/feature/metadata_edit_and_delete

Feature/metadata edit and delete
This commit is contained in:
Alex Coseru 2020-04-09 17:07:23 +03:00 committed by GitHub
commit 30a47e3dde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 249 additions and 10 deletions

View File

@ -1,6 +1,7 @@
import { URL } from 'whatwg-url' import { URL } from 'whatwg-url'
import { DDO } from '../ddo/DDO' import { DDO } from '../ddo/DDO'
import DID from '../ocean/DID' import DID from '../ocean/DID'
import { EditableMetaData } from '../ddo/MetaData'
import { Logger } from '../utils' import { Logger } from '../utils'
import { WebServiceConnector } from '../ocean/utils/WebServiceConnector' import { WebServiceConnector } from '../ocean/utils/WebServiceConnector'
@ -260,6 +261,90 @@ export class Aquarius {
return result return result
} }
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetaData Metadata fields & new values.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async editMetadata(
did: DID | string,
newMetadata: EditableMetaData,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/metadata/${did.getDid()}`
const data = Object()
if (newMetadata.description != null) data.description = newMetadata.description
if (newMetadata.title != null) data.title = newMetadata.title
if (newMetadata.servicePrices != null)
data.servicePrices = newMetadata.servicePrices
if (newMetadata.links != null) data.links = newMetadata.links
data.updated = updated
data.signature = signature
const result = await this.fetch
.put(fullUrl, JSON.stringify(data))
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log(
'editMetaData failed:',
response.status,
response.statusText
)
return null
})
.catch(error => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
/**
* Retire a DDO (Delete)
* @param {DID | string} did DID of the asset to update.
* @param {String} updated Updated field of the DDO
* @param {String} signature Signature using updated field to verify that the consumer has rights
* @return {Promise<String>} Result.
*/
public async retire(
did: DID | string,
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/${did.getDid()}`
const result = await this.fetch
.delete(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated
})
)
.then((response: any) => {
if (response.ok) {
return response.text
}
this.logger.log('retire failed:', response.status, response.statusText)
return null
})
.catch(error => {
this.logger.error('Error transfering ownership metadata: ', error)
return null
})
return result
}
public getServiceEndpoint(did: DID) { public getServiceEndpoint(did: DID) {
return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}` return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}`
} }

View File

@ -276,3 +276,28 @@ export interface MetaData {
additionalInformation?: AdditionalInformation additionalInformation?: AdditionalInformation
curation?: Curation curation?: Curation
} }
/** Warning. serviceIndex is the index of a services in Services array, and not service.index attribute.
Let's assume that you have the following services array:
[
{"index":1,"type":"access","main":{"price":3}},
{"index":0,"type":"compute","main":{"price":1}}
]
then calling update with { serviceIndex:1,price:2} will update the 'compute' service, and not the access one
**/
export interface ServicePrices {
serviceIndex: number
price: string
}
export interface EditableMetaDataLinks {
name: string
url: string
type: string
}
export interface EditableMetaData {
description?: string
title?: string
links?: EditableMetaDataLinks[]
servicePrices?: ServicePrices[]
}

View File

@ -1,7 +1,7 @@
import { TransactionReceipt } from 'web3-core' import { TransactionReceipt } from 'web3-core'
import { SearchQuery } from '../aquarius/Aquarius' import { SearchQuery } from '../aquarius/Aquarius'
import { DDO } from '../ddo/DDO' import { DDO } from '../ddo/DDO'
import { MetaData } from '../ddo/MetaData' import { MetaData, EditableMetaData } from '../ddo/MetaData'
import { Service, ServiceAccess } from '../ddo/Service' import { Service, ServiceAccess } from '../ddo/Service'
import Account from './Account' import Account from './Account'
import DID from './DID' import DID from './DID'
@ -384,6 +384,55 @@ export class OceanAssets extends Instantiable {
return txReceipt return txReceipt
} }
/**
* Edit Metadata for a DDO.
* @param {did} string DID.
* @param {newMetadata} EditableMetaData Metadata fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async editMetadata(
did: string,
newMetadata: EditableMetaData,
account: Account
): Promise<string> {
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.aquarius.editMetadata(
did,
newMetadata,
oldDdo.updated,
signature
)
return result
}
/**
* Retire a DDO (Delete)
* @param {did} string DID.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
*/
public async retire(did: string, account: Account): Promise<string> {
const oldDdo = await this.ocean.aquarius.retrieveDDO(did)
// get a signature
const signature = await this.ocean.utils.signature.signForAquarius(
oldDdo.updated,
account
)
let result = null
if (signature != null)
result = await this.ocean.aquarius.retire(did, oldDdo.updated, signature)
return result
}
/** /**
* Returns the assets of a consumer. * Returns the assets of a consumer.
* @param {string} consumer Consumer address. * @param {string} consumer Consumer address.

View File

@ -43,7 +43,16 @@ export class WebServiceConnector {
}) })
} }
public delete(url: string): Promise<Response> { public delete(url: string, payload?: BodyInit): Promise<Response> {
if (payload != null) {
return this.fetch(url, {
method: 'DELETE',
body: payload,
headers: {
'Content-type': 'application/json'
}
})
} else {
return this.fetch(url, { return this.fetch(url, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
@ -51,6 +60,7 @@ export class WebServiceConnector {
} }
}) })
} }
}
public async downloadFile( public async downloadFile(
url: string, url: string,

View File

@ -1,7 +1,7 @@
import { assert } from 'chai' import { assert } from 'chai'
import { config } from '../config' import { config } from '../config'
import { getMetadata } from '../utils' import { getMetadata } from '../utils'
import { Ocean, Account } from '../../../src' // @oceanprotocol/squid import { Ocean, Account, EditableMetaData } from '../../../src' // @oceanprotocol/squid
describe('Asset Owners', () => { describe('Asset Owners', () => {
let ocean: Ocean let ocean: Ocean
@ -84,8 +84,8 @@ describe('Asset Owners', () => {
const { length: finalLength1 } = await ocean.assets.consumerAssets( const { length: finalLength1 } = await ocean.assets.consumerAssets(
account2.getId() account2.getId()
) )
assert.equal(finalLength1 - initialLength, 0)
assert.equal(finalLength1 - initialLength, 0)
// Granting access // Granting access
try { try {
await account2.requestTokens( await account2.requestTokens(
@ -116,6 +116,76 @@ describe('Asset Owners', () => {
assert.equal(aquariusOwner, account2.getId()) assert.equal(aquariusOwner, account2.getId())
}) })
it('should be able to update metadata', async () => {
const { id } = await ocean.assets.create(metadata as any, account1)
const links = [
{
name: 'Sample1',
url: 'http://www.example.com',
type: 'sample'
},
{
name: 'Sample2',
url: 'http://www.example.net',
type: 'sample'
}
]
const newPrices = [
{
serviceIndex: 0,
price: '31000000000000000000'
},
{
serviceIndex: 2,
price: '31000000000000000000'
}
]
const newMetaData = {
title: 'New title',
description: 'New description',
links: links,
servicePrices: newPrices
}
await ocean.assets.editMetadata(id, newMetaData, account1)
const newDDO = await ocean.assets.resolve(id)
assert.equal(newDDO.service[0].attributes.main.name, 'New title')
assert.equal(
newDDO.service[0].attributes.additionalInformation.description,
'New description'
)
assert.equal(newDDO.service[0].attributes.main.price, '31000000000000000000')
assert.equal(newDDO.service[2].attributes.main.price, '31000000000000000000')
assert.equal(
newDDO.service[0].attributes.additionalInformation.links[0].name,
'Sample1'
)
assert.equal(
newDDO.service[0].attributes.additionalInformation.links[0].url,
'http://www.example.com'
)
assert.equal(
newDDO.service[0].attributes.additionalInformation.links[1].name,
'Sample2'
)
assert.equal(
newDDO.service[0].attributes.additionalInformation.links[1].url,
'http://www.example.net'
)
})
it('should be able to retire metadata', async () => {
const { id } = await ocean.assets.create(metadata as any, account1)
await ocean.assets.retire(id, account1)
const newDDO = await ocean.assets.resolve(id)
assert.equal(newDDO, null)
})
it('should add and remove correctly an address to/from FreeWhiteList on an asset', async () => { it('should add and remove correctly an address to/from FreeWhiteList on an asset', async () => {
const ddo = await ocean.assets.create(metadata as any, account1) const ddo = await ocean.assets.create(metadata as any, account1)
await ocean.assets.addConsumerToFreeWhiteList(ddo.id, consumer1.getId(), account1) await ocean.assets.addConsumerToFreeWhiteList(ddo.id, consumer1.getId(), account1)