1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

add updateServiceTimeout and edit ddo updates (#544)

* add updateServiceTimeout

* remove unnecessary code

* fix travis

* fix

* add fileinfo endpoint

* fix did problem

* namings refactor

* lint fix
This commit is contained in:
Alex Coseru 2021-01-18 12:02:38 +02:00 committed by GitHub
parent 3801c3925b
commit 16c21e1ecb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 137 additions and 189 deletions

View File

@ -29,7 +29,6 @@ before_script:
- export AQUARIUS_URI="http://172.15.0.5:5000"
- export DEPLOY_CONTRACTS="true"
- export CONTRACTS_VERSION=v0.5.7
- export PROVIDER_VERSION=latest
- bash -x start_ocean.sh --no-dashboard 2>&1 > start_ocean.log &
- cd ..
- ./scripts/waitforcontracts.sh

View File

@ -1,9 +1,7 @@
import { EditableMetadataLinks } from './EditableMetadataLinks'
import { ServicePrices } from './ServicePrices'
export interface EditableMetadata {
description?: string
title?: string
links?: EditableMetadataLinks[]
servicePrices?: ServicePrices[]
}

View File

@ -9,7 +9,13 @@ export interface File {
* File URL.
* @type {string}
*/
url: string
url?: string
/**
* Is URL accessible.
* @type {boolean}
*/
valid?: boolean
/**
* File index.

View File

@ -201,60 +201,6 @@ export class MetadataCache {
return result
}
/**
* Update Compute Privacy
* @param {DID | string} did DID of the asset to update.
* @param {number } serviceIndex Service index
* @param {boolean} allowRawAlgorithm Allow Raw Algorithms
* @param {boolean} allowNetworkAccess Allow Raw Algorithms
* @param {String[]} trustedAlgorithms Allow Raw Algorithms
* @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 updateComputePrivacy(
did: DID | string,
serviceIndex: number,
allowRawAlgorithm: boolean,
allowNetworkAccess: boolean,
trustedAlgorithms: string[],
updated: string,
signature: string
): Promise<string> {
did = did && DID.parse(did)
const fullUrl = `${this.url}${apiPath}/computePrivacy/update/${did.getDid()}`
const result = await this.fetch
.put(
fullUrl,
JSON.stringify({
signature: signature,
updated: updated,
serviceIndex: serviceIndex,
allowRawAlgorithm: allowRawAlgorithm,
allowNetworkAccess: allowNetworkAccess,
trustedAlgorithms: trustedAlgorithms
})
)
.then((response: Response) => {
if (response.ok) {
return response.text
}
this.logger.log(
'update compute privacy failed:',
response.status,
response.statusText
)
return null
})
.catch((error) => {
this.logger.error('Error updating compute privacy: ', error)
return null
})
return result
}
public async getOwnerAssets(owner: string): Promise<QueryResult> {
const q = {
offset: 100,
@ -271,47 +217,6 @@ export class MetadataCache {
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: Response) => {
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.

View File

@ -239,82 +239,52 @@ export class Assets extends Instantiable {
return (await this.ocean.metadatacache.queryMetadata(searchQuery)).results
}
/**
* 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>}
/** Metadata updates
* Don't forget to call ocean.OnChainMetadataCache.update after using this functions
* ie: ocean.OnChainMetadataCache.update(ddo.id,ddo,account.getId())
*/
public async editMetadata(
did: string,
newMetadata: EditableMetadata,
account: Account
): Promise<DDO> {
const oldDdo = await this.ocean.metadatacache.retrieveDDO(did)
let i
for (i = 0; i < oldDdo.service.length; i++) {
if (oldDdo.service[i].type === 'metadata') {
if (newMetadata.title) oldDdo.service[i].attributes.main.name = newMetadata.title
if (!oldDdo.service[i].attributes.additionalInformation)
oldDdo.service[i].attributes.additionalInformation = Object()
if (newMetadata.description)
oldDdo.service[i].attributes.additionalInformation.description =
newMetadata.description
if (newMetadata.links)
oldDdo.service[i].attributes.additionalInformation.links = newMetadata.links
}
/**
* Edit Metadata for a DID.
* @param {ddo} DDO if empty, will trigger a retrieve
* @param {newMetadata} EditableMetadata Metadata fields & new values.
* @return {Promise<DDO>} the new DDO
*/
public async editMetadata(ddo: DDO, newMetadata: EditableMetadata): Promise<DDO> {
if (!ddo) return null
for (let i = 0; i < ddo.service.length; i++) {
if (ddo.service[i].type !== 'metadata') continue
if (newMetadata.title) ddo.service[i].attributes.main.name = newMetadata.title
if (!ddo.service[i].attributes.additionalInformation)
ddo.service[i].attributes.additionalInformation = Object()
if (newMetadata.description)
ddo.service[i].attributes.additionalInformation.description =
newMetadata.description
if (newMetadata.links)
ddo.service[i].attributes.additionalInformation.links = newMetadata.links
}
if (newMetadata.servicePrices) {
for (i = 0; i < newMetadata.servicePrices.length; i++) {
if (
newMetadata.servicePrices[i].cost &&
newMetadata.servicePrices[i].serviceIndex
) {
oldDdo.service[newMetadata.servicePrices[i].serviceIndex].attributes.main.cost =
newMetadata.servicePrices[i].cost
}
}
}
const storeTx = await this.ocean.OnChainMetadataCache.update(
oldDdo.id,
oldDdo,
account.getId()
)
if (storeTx) return oldDdo
else return null
return ddo
}
/**
* Update Compute Privacy
* @param {did} string DID.
* @param {number} serviceIndex Index of the compute service in the DDO
* @param {ServiceComputePrivacy} computePrivacy ComputePrivacy fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<string>}
* Edit Service Timeouts
* @param {ddo} DDO if empty, will trigger a retrieve
* @param {number} serviceIndex Index of the compute service in the DDO.
* @param {number} timeout New timeout setting
* @return {Promise<DDO>}
*/
public async updateComputePrivacy(
did: string,
public async editServiceTimeout(
ddo: DDO,
serviceIndex: number,
computePrivacy: ServiceComputePrivacy,
account: Account
timeout: number
): Promise<DDO> {
const oldDdo = await this.ocean.metadatacache.retrieveDDO(did)
if (oldDdo.service[serviceIndex].type !== 'compute') return null
oldDdo.service[serviceIndex].attributes.main.privacy.allowRawAlgorithm =
computePrivacy.allowRawAlgorithm
oldDdo.service[serviceIndex].attributes.main.privacy.allowNetworkAccess =
computePrivacy.allowNetworkAccess
oldDdo.service[serviceIndex].attributes.main.privacy.trustedAlgorithms =
computePrivacy.trustedAlgorithms
const storeTx = await this.ocean.OnChainMetadataCache.update(
oldDdo.id,
oldDdo,
account.getId()
)
if (storeTx) return oldDdo
else return null
if (!ddo) return null
if (typeof ddo.service[serviceIndex] === 'undefined') return null
if (timeout < 0) return null
ddo.service[serviceIndex].attributes.main.timeout = parseInt(timeout.toFixed())
return ddo
}
/** End metadata updates */
/**
* Returns the creator of a asset.

View File

@ -433,4 +433,35 @@ export class Compute extends Instantiable {
return order
})
}
/**
* Edit Compute Privacy
* @param {did} string DID. You can leave this empty if you already have the DDO
* @param {ddo} DDO if empty, will trigger a retrieve
* @param {number} serviceIndex Index of the compute service in the DDO. If -1, will try to find it
* @param {ServiceComputePrivacy} computePrivacy ComputePrivacy fields & new values.
* @param {Account} account Ethereum account of owner to sign and prove the ownership.
* @return {Promise<DDO>}
*/
public async editComputePrivacy(
ddo: DDO,
serviceIndex: number,
computePrivacy: ServiceComputePrivacy
): Promise<DDO> {
if (!ddo) return null
if (serviceIndex === -1) {
const service = ddo.findServiceByType('compute')
if (!service) return null
serviceIndex = service.index
}
if (typeof ddo.service[serviceIndex] === 'undefined') return null
if (ddo.service[serviceIndex].type !== 'compute') return null
ddo.service[serviceIndex].attributes.main.privacy.allowRawAlgorithm =
computePrivacy.allowRawAlgorithm
ddo.service[serviceIndex].attributes.main.privacy.allowNetworkAccess =
computePrivacy.allowNetworkAccess
ddo.service[serviceIndex].attributes.main.privacy.trustedAlgorithms =
computePrivacy.trustedAlgorithms
return ddo
}
}

View File

@ -8,6 +8,7 @@ import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
import { Versions } from '../ocean/Versions'
import { Response } from 'node-fetch'
import { DDO } from '../ddo/DDO'
import DID from '../ocean/DID'
const apiPath = '/api/v1/services'
@ -73,20 +74,28 @@ export class Provider extends Instantiable {
}
}
public async checkURL(url: string): Promise<Record<string, string>> {
const args = { url }
/** Get URL details (if possible)
* @param {String | DID} url or did
* @return {Promise<File[]>} urlDetails
*/
public async fileinfo(url: string | DID): Promise<File[]> {
let args
const files: File[] = []
if (url instanceof DID) {
args = { did: url.getDid() }
} else args = { url }
try {
const response = await this.ocean.utils.fetch.post(
this.getCheckURLEndpoint(),
decodeURI(JSON.stringify(args))
this.getFileinfoEndpoint(),
JSON.stringify(args)
)
const result = await response.json()
return result.result
const results: File[] = await response.json()
for (const result of results) {
files.push(result)
}
return files
} catch (e) {
this.logger.error(e)
throw new Error('HTTP request failed')
return null
}
}
@ -298,8 +307,8 @@ export class Provider extends Instantiable {
return `${this.url}${apiPath}/encrypt`
}
public getCheckURLEndpoint(): string {
return `${this.url}${apiPath}/checkURL`
public getFileinfoEndpoint(): string {
return `${this.url}${apiPath}/fileinfo`
}
public getPublishEndpoint(): string {

View File

@ -468,13 +468,14 @@ describe('Compute flow', () => {
}
}
assert(computeIndex > 0)
const newDdo = await ocean.assets.updateComputePrivacy(
ddo.id,
const newDdo = await ocean.compute.editComputePrivacy(
ddo,
computeIndex,
newComputePrivacy,
alice
newComputePrivacy
)
assert(newDdo !== null)
const txid = await ocean.OnChainMetadataCache.update(newDdo.id, newDdo, alice.getId())
assert(txid !== null)
await sleep(60000)
const metaData = await ocean.assets.getServiceByType(ddo.id, 'compute')
assert.equal(

View File

@ -5,7 +5,8 @@ import spies from 'chai-spies'
import Web3 from 'web3'
import { AbiItem } from 'web3-utils/types'
import { DataTokens } from '../../src/datatokens/Datatokens'
import { Account, EditableMetadata, Service, ServiceAccess } from '../../src/lib'
import { Account, EditableMetadata, Service, ServiceAccess, DID } from '../../src/lib'
import { noDidPrefixed } from '../../src/utils/'
import { Ocean } from '../../src/ocean/Ocean'
import { ConfigHelper } from '../../src/utils/ConfigHelper'
import { TestContractHandler } from '../TestContractHandler'
@ -89,8 +90,7 @@ describe('Marketplace flow', () => {
license: 'MIT',
files: [
{
url:
'https://raw.githubusercontent.com/tbertinmahieux/MSongsDB/master/Tasks_Demos/CoverSongs/shs_dataset_test.txt',
url: 'https://s3.amazonaws.com/testfiles.oceanprotocol.com/info.0.json',
checksum: 'efb2c764274b745f5fc37f97c6b0e761',
contentLength: '4535431',
contentType: 'text/csv',
@ -212,8 +212,10 @@ describe('Marketplace flow', () => {
title: 'new title',
links: [{ name: 'link1', type: 'sample', url: 'http://example.net' }]
}
const newDdo = await ocean.assets.editMetadata(ddo.id, newMetaData, alice)
const newDdo = await ocean.assets.editMetadata(ddo, newMetaData)
assert(newDdo !== null)
const txid = await ocean.OnChainMetadataCache.update(newDdo.id, newDdo, alice.getId())
assert(txid !== null)
await sleep(60000)
const metaData = await ocean.assets.getServiceByType(ddo.id, 'metadata')
assert.equal(metaData.attributes.main.name, newMetaData.title)
@ -224,6 +226,28 @@ describe('Marketplace flow', () => {
assert.deepEqual(metaData.attributes.additionalInformation.links, newMetaData.links)
})
it('Alice updates timeout for the access service', async () => {
const service = ddo.findServiceByType('access')
assert(service !== null)
const serviceIndex = service.index
const newTimeout = 123
const newDdo = await ocean.assets.editServiceTimeout(ddo, serviceIndex, newTimeout)
assert(newDdo !== null)
const txid = await ocean.OnChainMetadataCache.update(newDdo.id, newDdo, alice.getId())
assert(txid !== null)
await sleep(60000)
const metaData = await ocean.assets.getServiceByType(ddo.id, 'access')
assert(parseInt(metaData.attributes.main.timeout) === parseInt(newTimeout.toFixed()))
})
it('Alice should check if her asset has valid url(s)', async () => {
const did: DID = DID.generate(noDidPrefixed(ddo.id))
const response = await ocean.provider.fileinfo(did)
assert(response[0].valid === true)
assert(response[0].contentLength === '1161')
assert(response[0].contentType === 'application/json')
})
it('Alice publishes a dataset but passed data token is invalid', async () => {
price = '10' // in datatoken
const publishedDate = new Date(Date.now()).toISOString().split('.')[0] + 'Z'

View File

@ -18,8 +18,13 @@ describe('Provider tests', () => {
})
it('Check a valid URL', async () => {
const url = 'https://s3.amazonaws.com/testfiles.oceanprotocol.com/info.0.json'
const response = await ocean.provider.checkURL(url)
assert(response.contentLength === '1161')
assert(response.contentType === 'application/json')
const response = await ocean.provider.fileinfo(url)
assert(response[0].contentLength === '1161')
assert(response[0].contentType === 'application/json')
})
it('Check a invalid URL', async () => {
const url = 'https://s3.amazonaws.com/testfiles.oceanprotocol.com/nosuchfile'
const response = await ocean.provider.fileinfo(url)
assert(response[0].valid === false)
})
})