implement file uploading

This commit is contained in:
Sofía Aritz 2024-06-16 20:39:10 +02:00
parent 36a5df1665
commit abdf5c2229
Signed by: sofia
GPG key ID: 90B5116E3542B28F
5 changed files with 128 additions and 15 deletions

View file

@ -11,3 +11,6 @@
#!.yarn/cache #!.yarn/cache
.pnp.* .pnp.*
.keys
.assets

View file

@ -1,10 +1,12 @@
import { readFile } from "node:fs/promises" import { readFile } from "node:fs/promises"
import { readFileSync } from "node:fs"; import { createWriteStream, readFileSync, writeFileSync } from "node:fs";
import { createSign } from "node:crypto"; import { createSign, generateKeyPairSync, randomUUID } from "node:crypto";
import Fastify from "fastify"; import Fastify from "fastify";
import multipart from '@fastify/multipart'
import { join } from "node:path"; import { join } from "node:path";
import mime from "mime" import mime from "mime"
import { assert } from "node:console"; import { promisify } from "node:util";
import { pipeline } from "node:stream";
const M2M_ALGORITHM = "RSA-SHA512" const M2M_ALGORITHM = "RSA-SHA512"
const { private: M2M_PRIVATE_KEY, public: M2M_PUBLIC_KEY } = loadM2MKeys() const { private: M2M_PRIVATE_KEY, public: M2M_PUBLIC_KEY } = loadM2MKeys()
@ -13,7 +15,7 @@ if (M2M_PRIVATE_KEY == null || M2M_PUBLIC_KEY == null) {
process.exit(1) process.exit(1)
} }
const ASSETS_FOLDER = "../.assets/" const ASSETS_FOLDER = "./.assets/"
const ASSET_API_LANDING_MESSAGE = "asset-api v1.0.0" const ASSET_API_LANDING_MESSAGE = "asset-api v1.0.0"
const IDENTITY_API_ENDPOINT = "http://localhost:3000" const IDENTITY_API_ENDPOINT = "http://localhost:3000"
@ -22,6 +24,8 @@ const fastify = new Fastify({
logger: true, logger: true,
}) })
fastify.register(multipart)
fastify.get("/", async (request, reply) => { fastify.get("/", async (request, reply) => {
return signString(ASSET_API_LANDING_MESSAGE) return signString(ASSET_API_LANDING_MESSAGE)
}) })
@ -36,10 +40,25 @@ fastify.get("/crypto/algo", (request, reply) => {
fastify.put("/asset", { fastify.put("/asset", {
async handler(request, reply) { async handler(request, reply) {
let user = await userFromSessionKey(request.query.session_key) await userFromSessionKey(request.query.session_key)
let file = await request.file()
// continue working onmthis let id = randomUUID().toString()
console.log(typeof request.body) let extension = mime.getExtension(file.mimetype) || ".bin"
let full_id = `${id}.${extension}`
let url = new URL(IDENTITY_API_ENDPOINT)
url.pathname = "/m2m/asset"
await fetch(url, {
method: "PUT",
body: signObject({
session_key: request.query.session_key,
asset_id: full_id,
})
})
promisify(pipeline)(file.file, createWriteStream(`.assets/${full_id}`))
}, },
schema: { schema: {
query: { query: {
@ -80,9 +99,30 @@ fastify.get("/asset", {
fastify.listen({ port: 3001 }) fastify.listen({ port: 3001 })
function loadM2MKeys() { function loadM2MKeys() {
try {
return { return {
private: readFileSync("../.keys/m2m-dev.pem").toString("ascii"), private: readFileSync("./.keys/m2m.pem").toString("ascii"),
public: readFileSync("../.keys/m2m-dev.pub").toString("ascii"), public: readFileSync("./.keys/m2m.pub").toString("ascii"),
}
} catch (e) {
console.warn("Generating M2M key pair!")
let { publicKey, privateKey } = generateKeyPairSync("rsa", {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
},
})
writeFileSync("./.keys/m2m.pem", privateKey)
writeFileSync("./.keys/m2m.pub", publicKey)
return loadM2MKeys()
} }
} }
@ -103,7 +143,7 @@ async function userFromSessionKey(session_key) {
let res1 = await fetch(url, { let res1 = await fetch(url, {
method: "POST", method: "POST",
body: signObject({ body: signObject({
session_key: request.query.session_key, session_key,
}) })
}) })

View file

@ -4,6 +4,7 @@
"type": "module", "type": "module",
"packageManager": "yarn@4.3.0", "packageManager": "yarn@4.3.0",
"dependencies": { "dependencies": {
"@fastify/multipart": "^8.3.0",
"fastify": "^4.28.0", "fastify": "^4.28.0",
"mime": "^4.0.3", "mime": "^4.0.3",
"uuid": "^10.0.0" "uuid": "^10.0.0"

View file

@ -16,7 +16,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@fastify/error@npm:^3.3.0, @fastify/error@npm:^3.4.0": "@fastify/busboy@npm:^2.1.0":
version: 2.1.1
resolution: "@fastify/busboy@npm:2.1.1"
checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3
languageName: node
linkType: hard
"@fastify/deepmerge@npm:^1.0.0":
version: 1.3.0
resolution: "@fastify/deepmerge@npm:1.3.0"
checksum: 10c0/8115ed7b891189ee4ebba554a105cb69111615bdb2961f8c58a80872fac9d7b74b2c6317d545a7d378325d094ce73a91fc9c5d7d6189476779cd5a5493cb1351
languageName: node
linkType: hard
"@fastify/error@npm:^3.0.0, @fastify/error@npm:^3.3.0, @fastify/error@npm:^3.4.0":
version: 3.4.1 version: 3.4.1
resolution: "@fastify/error@npm:3.4.1" resolution: "@fastify/error@npm:3.4.1"
checksum: 10c0/1f1a0faa8c86639afb6f4bd47a9cdc1f0f20ce0d6944340fbdec8218aaba91dc9cae9ed78e24e61bceb782a867efda2b9a6320091f00dcbb896d9c8a9bdf5f96 checksum: 10c0/1f1a0faa8c86639afb6f4bd47a9cdc1f0f20ce0d6944340fbdec8218aaba91dc9cae9ed78e24e61bceb782a867efda2b9a6320091f00dcbb896d9c8a9bdf5f96
@ -41,6 +55,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@fastify/multipart@npm:^8.3.0":
version: 8.3.0
resolution: "@fastify/multipart@npm:8.3.0"
dependencies:
"@fastify/busboy": "npm:^2.1.0"
"@fastify/deepmerge": "npm:^1.0.0"
"@fastify/error": "npm:^3.0.0"
fastify-plugin: "npm:^4.0.0"
secure-json-parse: "npm:^2.4.0"
stream-wormhole: "npm:^1.1.0"
checksum: 10c0/1021675af149435b1e585cfcaf8aba848c3799cbc213c18a0e3d74c6d64d21db27572a99295a8da5263f5562869452234dea2680e83e248456d97b560fb627eb
languageName: node
linkType: hard
"abort-controller@npm:^3.0.0": "abort-controller@npm:^3.0.0":
version: 3.0.0 version: 3.0.0
resolution: "abort-controller@npm:3.0.0" resolution: "abort-controller@npm:3.0.0"
@ -101,6 +129,7 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "asset-api@workspace:." resolution: "asset-api@workspace:."
dependencies: dependencies:
"@fastify/multipart": "npm:^8.3.0"
fastify: "npm:^4.28.0" fastify: "npm:^4.28.0"
mime: "npm:^4.0.3" mime: "npm:^4.0.3"
uuid: "npm:^10.0.0" uuid: "npm:^10.0.0"
@ -221,6 +250,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"fastify-plugin@npm:^4.0.0":
version: 4.5.1
resolution: "fastify-plugin@npm:4.5.1"
checksum: 10c0/f58f79cd9d3c88fd7f79a3270276c6339fc57bbe72ef14d20b73779193c404e317ac18e8eae2c5071b3909ebee45d7eb6871da4e65464ac64ed0d9746b4e9b9f
languageName: node
linkType: hard
"fastify@npm:^4.28.0": "fastify@npm:^4.28.0":
version: 4.28.0 version: 4.28.0
resolution: "fastify@npm:4.28.0" resolution: "fastify@npm:4.28.0"
@ -476,7 +512,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"secure-json-parse@npm:^2.7.0": "secure-json-parse@npm:^2.4.0, secure-json-parse@npm:^2.7.0":
version: 2.7.0 version: 2.7.0
resolution: "secure-json-parse@npm:2.7.0" resolution: "secure-json-parse@npm:2.7.0"
checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4 checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4
@ -515,6 +551,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"stream-wormhole@npm:^1.1.0":
version: 1.1.0
resolution: "stream-wormhole@npm:1.1.0"
checksum: 10c0/50800bcc919c01085b0bafa175c61a0c0bec27987dcc20aec92f8125bdc8b191102a030e114760d2ac86265eea65627d0145eea3adb8cb4453b3295e4468661a
languageName: node
linkType: hard
"string_decoder@npm:^1.3.0": "string_decoder@npm:^1.3.0":
version: 1.3.0 version: 1.3.0
resolution: "string_decoder@npm:1.3.0" resolution: "string_decoder@npm:1.3.0"

View file

@ -11,8 +11,31 @@ const JWT_SECRET = new TextEncoder().encode(
const JWT_ALG = 'HS256' const JWT_ALG = 'HS256'
const ASSET_API_ENDPOINT = "http://localhost:3001/" const ASSET_API_ENDPOINT = "http://localhost:3001/"
const ASSET_API_PUBKEY = await loadAssetPubkey() let ASSET_API_PUBKEY = await loadAssetPubkey()
const ASSET_API_ALGORITHM = await loadAssetAlgo() let ASSET_API_ALGORITHM = await loadAssetAlgo()
setInterval(async () => {
try {
let pubkey = await loadAssetPubkey()
let algo = await loadAssetAlgo()
if (pubkey != null && algo != null) {
if (ASSET_API_PUBKEY !== pubkey) {
console.warn("The M2M public key has changed!")
}
if (ASSET_API_ALGORITHM !== algo) {
console.warn("The M2M algorith has changed!")
}
ASSET_API_PUBKEY = pubkey
ASSET_API_ALGORITHM = algo
console.debug("Successfully updated the M2M public key and algorithm")
}
} catch (e) {
console.warn("Failed to update the M2M public key", e)
}
}, 60 * 1000)
let session_keys = { let session_keys = {
'uid:005d6417-a23c-48bd-b348-eafeae649b94': 'e381ba8c-e18a-4bca-afce-b212b37bc26b', 'uid:005d6417-a23c-48bd-b348-eafeae649b94': 'e381ba8c-e18a-4bca-afce-b212b37bc26b',
@ -22,6 +45,7 @@ let session_keys = {
let users = { let users = {
'jane@identity.net': { 'jane@identity.net': {
uid: '005d6417-a23c-48bd-b348-eafeae649b94', uid: '005d6417-a23c-48bd-b348-eafeae649b94',
email: 'jane@identity.net',
password: '12345678901234567890', password: '12345678901234567890',
name: 'Jane Doe', name: 'Jane Doe',
assets: ["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"], assets: ["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"],
@ -50,6 +74,7 @@ fastify.put("/m2m/asset", {
assert(user.length === 1) assert(user.length === 1)
users[user[0].email].assets.push(body.asset_id) users[user[0].email].assets.push(body.asset_id)
console.log(users[user[0].email].assets)
} }
}) })
@ -154,6 +179,7 @@ fastify.post('/auth/register', {
if (users[request.body.email] == null) { if (users[request.body.email] == null) {
users[request.body.email] = { users[request.body.email] = {
uid: uuidv4(), uid: uuidv4(),
email: request.body.email,
password: request.body.password, password: request.body.password,
name: request.body.name, name: request.body.name,
assets: [], assets: [],