53 lines
1.5 KiB
JavaScript
53 lines
1.5 KiB
JavaScript
|
const { gql } = require('apollo-server-micro')
|
||
|
const stringifyCanon = require('canonical-json')
|
||
|
const { createHash } = require('crypto')
|
||
|
const Ots = require('opentimestamps')
|
||
|
|
||
|
const ITEM_OTS_FIELDS = gql`
|
||
|
fragment ItemOTSFields on Item {
|
||
|
parentId
|
||
|
parentOtsHash
|
||
|
title
|
||
|
text
|
||
|
url
|
||
|
}`
|
||
|
|
||
|
function timestampItem ({ apollo, models }) {
|
||
|
return async function ({ data: { id } }) {
|
||
|
console.log('timestamping item', id)
|
||
|
|
||
|
const { data: { item: { parentId, parentOtsHash, title, text, url } } } = await apollo.query({
|
||
|
query: gql`
|
||
|
${ITEM_OTS_FIELDS}
|
||
|
query Item {
|
||
|
item(id: ${id}) {
|
||
|
...ItemOTSFields
|
||
|
}
|
||
|
}`
|
||
|
})
|
||
|
|
||
|
if (parentId && !parentOtsHash) {
|
||
|
console.log('no parent hash available ... skipping')
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// SHA256 hash item using a canonical serialization format { parentHash, title, text, url }
|
||
|
const itemString = stringifyCanon({ parentHash: parentOtsHash, title, text, url })
|
||
|
const otsHash = createHash('sha256').update(itemString).digest()
|
||
|
const detached = Ots.DetachedTimestampFile.fromHash(new Ots.Ops.OpSHA256(), otsHash)
|
||
|
|
||
|
// timestamp it
|
||
|
await Ots.stamp(detached)
|
||
|
|
||
|
// get proof
|
||
|
const otsFile = Buffer.from(detached.serializeToBytes())
|
||
|
|
||
|
// store in item
|
||
|
await models.item.update({ where: { id }, data: { otsHash: otsHash.toString('hex'), otsFile } })
|
||
|
|
||
|
console.log('done timestamping item', id)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = { timestampItem }
|