diff --git a/README.md b/README.md index 8ae5555..e879d22 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Remaining: - parameterize bucket for test server - try American Cloud - dockerize +- add file extension +- images.timesafari.app - pretty-up the client, show thumbnail diff --git a/server.js b/server.js index 41a8904..52f5e69 100644 --- a/server.js +++ b/server.js @@ -19,6 +19,7 @@ app.use(cors()); const port = process.env.PORT || 3001; // file name also referenced in flyway.conf and potentially in .env files or in environment variables const dbFile = process.env.SQLITE_FILE || './image-db.sqlite'; +const bucketName = process.env.AWS_BUCKET_NAME || 'gifts-image-test'; const ethrDidResolver = getResolver; const resolver = @@ -51,6 +52,10 @@ const uploadMulter = multer({ dest: uploadDir + '/' }); // POST endpoint to upload an image app.post('/image', uploadMulter.single('image'), async (req, res) => { + const reqFile = req.file; + if (reqFile == null) { + return res.status(400).send(JSON.stringify({ success: false, message: 'No file uploaded.' })); + } // Verify the JWT try { @@ -62,7 +67,7 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { const verified = await didJwt.verifyJWT(jwt, { resolver }); if (!verified.verified) { const errorTime = new Date().toISOString(); - console.log(errorTime, 'Got invalid JWT in Authorization header:', verified); + console.error(errorTime, 'Got invalid JWT in Authorization header:', verified); return res.status(401).send(JSON.stringify({ success: false, message: 'Got invalid JWT in Authorization header. See server logs at ' + errorTime })); } const issuerDid = verified.issuer; @@ -74,7 +79,7 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { [ issuerDid ], (dbErr, row) => { if (dbErr) { - console.error('Error getting user record from database:', dbErr) + console.error('Error getting user record from database (but continuing):', dbErr) // may not matter, so continue } resolve(row?.per_week); @@ -100,7 +105,7 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { [issuerDid, limitPerWeek], (dbErr) => { if (dbErr) { - console.error("Error inserting user record for", issuerDid, "into database:", dbErr); + console.error("Error inserting user record for", issuerDid, "into database (but continuing):", dbErr); // we can continue... it just means we'll check the endorser server again next time } resolve(); @@ -123,7 +128,7 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { [issuerDid, startOfWeekString], (dbErr, row) => { if (dbErr) { - console.error(currentDate, "Error counting records for", issuerDid, "into database:", dbErr); + console.error(currentDate, "Error counting records for", issuerDid, "into database (but continuing):", dbErr); // we can continue... it just means we'll check the endorser server again next time } resolve(row?.week_count); @@ -135,27 +140,20 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { } // Read the file from the temporary location - fs.readFile(req.file.path, async (err, data) => { + fs.readFile(reqFile.path, async (err, data) => { if (err) throw err; // Handle error const hashSum = crypto.createHash('sha256'); hashSum.update(data); const hashHex = hashSum.digest('hex'); - const bucketName = 'gifts-image'; const fileName = hashHex; - const params = { - Body: data, - Bucket: bucketName, // S3 Bucket name - ContentType: req.file.mimetype, // File content type - Key: fileName, // File name to use in S3 - }; try { // record the upload in the database const currentDate = new Date().toISOString(); - const localFile = req.file.path.startsWith(uploadDir + '/') ? req.file.path.substring(uploadDir.length + 1) : req.file.path; + const localFile = reqFile.path.startsWith(uploadDir + '/') ? reqFile.path.substring(uploadDir.length + 1) : reqFile.path; const finalUrl = `https://${bucketName}.s3.amazonaws.com/${fileName}`; await new Promise((resolve, reject) => { db.run( @@ -164,7 +162,7 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { currentDate, issuerDid, localFile, - req.file.size, + reqFile.size, fileName, finalUrl ], @@ -180,6 +178,12 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { }); // send to AWS + const params = { + Body: data, + Bucket: bucketName, // S3 Bucket name + ContentType: reqFile.mimetype, // File content type + Key: fileName, // File name to use in S3 + }; const command = new PutObjectCommand(params); const response = await s3Client.send(command); if (response.$metadata.httpStatusCode !== 200) { @@ -190,9 +194,9 @@ app.post('/image', uploadMulter.single('image'), async (req, res) => { message: "Got bad status of " + response.$metadata.httpStatusCode + " from AWS. See server logs at " + errorTime })); } else { - fs.rm(req.file.path, (err) => { + fs.rm(reqFile.path, (err) => { if (err) { - console.error("Error deleting temp file", req.file.path, "with error:", err); + console.error("Error deleting temp file", reqFile.path, "with error (but continuing):", err); } }); res.send(JSON.stringify({success: true, url: finalUrl}));