diff --git a/asset-api/.gitignore b/asset-api/.gitignore index 870eb6a..cef240f 100644 --- a/asset-api/.gitignore +++ b/asset-api/.gitignore @@ -11,3 +11,6 @@ #!.yarn/cache .pnp.* + +.keys +.assets \ No newline at end of file diff --git a/asset-api/index.js b/asset-api/index.js index 9624991..e35111d 100644 --- a/asset-api/index.js +++ b/asset-api/index.js @@ -1,10 +1,12 @@ import { readFile } from "node:fs/promises" -import { readFileSync } from "node:fs"; -import { createSign } from "node:crypto"; +import { createWriteStream, readFileSync, writeFileSync } from "node:fs"; +import { createSign, generateKeyPairSync, randomUUID } from "node:crypto"; import Fastify from "fastify"; +import multipart from '@fastify/multipart' import { join } from "node:path"; 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 { 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) } -const ASSETS_FOLDER = "../.assets/" +const ASSETS_FOLDER = "./.assets/" const ASSET_API_LANDING_MESSAGE = "asset-api v1.0.0" const IDENTITY_API_ENDPOINT = "http://localhost:3000" @@ -22,6 +24,8 @@ const fastify = new Fastify({ logger: true, }) +fastify.register(multipart) + fastify.get("/", async (request, reply) => { return signString(ASSET_API_LANDING_MESSAGE) }) @@ -36,10 +40,25 @@ fastify.get("/crypto/algo", (request, reply) => { fastify.put("/asset", { 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 - console.log(typeof request.body) + let id = randomUUID().toString() + 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: { query: { @@ -80,9 +99,30 @@ fastify.get("/asset", { fastify.listen({ port: 3001 }) function loadM2MKeys() { - return { - private: readFileSync("../.keys/m2m-dev.pem").toString("ascii"), - public: readFileSync("../.keys/m2m-dev.pub").toString("ascii"), + try { + return { + private: readFileSync("./.keys/m2m.pem").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, { method: "POST", body: signObject({ - session_key: request.query.session_key, + session_key, }) }) diff --git a/asset-api/package.json b/asset-api/package.json index 0f5ff59..75527aa 100644 --- a/asset-api/package.json +++ b/asset-api/package.json @@ -4,6 +4,7 @@ "type": "module", "packageManager": "yarn@4.3.0", "dependencies": { + "@fastify/multipart": "^8.3.0", "fastify": "^4.28.0", "mime": "^4.0.3", "uuid": "^10.0.0" diff --git a/asset-api/yarn.lock b/asset-api/yarn.lock index c52c71b..dce94a8 100644 --- a/asset-api/yarn.lock +++ b/asset-api/yarn.lock @@ -16,7 +16,21 @@ __metadata: languageName: node 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 resolution: "@fastify/error@npm:3.4.1" checksum: 10c0/1f1a0faa8c86639afb6f4bd47a9cdc1f0f20ce0d6944340fbdec8218aaba91dc9cae9ed78e24e61bceb782a867efda2b9a6320091f00dcbb896d9c8a9bdf5f96 @@ -41,6 +55,20 @@ __metadata: languageName: node 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": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -101,6 +129,7 @@ __metadata: version: 0.0.0-use.local resolution: "asset-api@workspace:." dependencies: + "@fastify/multipart": "npm:^8.3.0" fastify: "npm:^4.28.0" mime: "npm:^4.0.3" uuid: "npm:^10.0.0" @@ -221,6 +250,13 @@ __metadata: languageName: node 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": version: 4.28.0 resolution: "fastify@npm:4.28.0" @@ -476,7 +512,7 @@ __metadata: languageName: node 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 resolution: "secure-json-parse@npm:2.7.0" checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4 @@ -515,6 +551,13 @@ __metadata: languageName: node 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": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" diff --git a/identity-api/index.js b/identity-api/index.js index febc679..cbe877f 100644 --- a/identity-api/index.js +++ b/identity-api/index.js @@ -11,8 +11,31 @@ const JWT_SECRET = new TextEncoder().encode( const JWT_ALG = 'HS256' const ASSET_API_ENDPOINT = "http://localhost:3001/" -const ASSET_API_PUBKEY = await loadAssetPubkey() -const ASSET_API_ALGORITHM = await loadAssetAlgo() +let ASSET_API_PUBKEY = await loadAssetPubkey() +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 = { 'uid:005d6417-a23c-48bd-b348-eafeae649b94': 'e381ba8c-e18a-4bca-afce-b212b37bc26b', @@ -22,6 +45,7 @@ let session_keys = { let users = { 'jane@identity.net': { uid: '005d6417-a23c-48bd-b348-eafeae649b94', + email: 'jane@identity.net', password: '12345678901234567890', name: 'Jane Doe', assets: ["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"], @@ -50,6 +74,7 @@ fastify.put("/m2m/asset", { assert(user.length === 1) 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) { users[request.body.email] = { uid: uuidv4(), + email: request.body.email, password: request.body.password, name: request.body.name, assets: [],