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:
parent
3801c3925b
commit
16c21e1ecb
@ -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
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { EditableMetadataLinks } from './EditableMetadataLinks'
|
||||
import { ServicePrices } from './ServicePrices'
|
||||
|
||||
export interface EditableMetadata {
|
||||
description?: string
|
||||
title?: string
|
||||
links?: EditableMetadataLinks[]
|
||||
servicePrices?: ServicePrices[]
|
||||
}
|
||||
|
@ -9,7 +9,13 @@ export interface File {
|
||||
* File URL.
|
||||
* @type {string}
|
||||
*/
|
||||
url: string
|
||||
url?: string
|
||||
|
||||
/**
|
||||
* Is URL accessible.
|
||||
* @type {boolean}
|
||||
*/
|
||||
valid?: boolean
|
||||
|
||||
/**
|
||||
* File index.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user