Преглед изворни кода

Merge pull request #22334 from overleaf/ar-guard-against-integer-like-strings-when-working-with-postgres

[history-v1] Guard against non-postgres projectIds

GitOrigin-RevId: 5bf75c67424297f52f2abd9d0f0f14a0f79f8921
Andrew Rumble пре 1 година
родитељ
комит
31e8a908ee

+ 5 - 0
services/history-v1/storage/lib/assert.js

@@ -40,6 +40,10 @@ function mongoId(arg, message) {
   assert.match(arg, MONGO_ID_REGEXP)
 }
 
+function postgresId(arg, message) {
+  assert.match(arg, POSTGRES_ID_REGEXP, message)
+}
+
 module.exports = {
   ...assert,
   transaction,
@@ -47,6 +51,7 @@ module.exports = {
   projectId,
   chunkId,
   mongoId,
+  postgresId,
   MONGO_ID_REGEXP,
   POSTGRES_ID_REGEXP,
 }

+ 5 - 5
services/history-v1/storage/lib/blob_store/postgres.js

@@ -13,8 +13,8 @@ async function initialize(projectId) {
  * Return blob metadata for the given project and hash
  */
 async function findBlob(projectId, hash) {
+  assert.postgresId(projectId, `bad projectId ${projectId}`)
   projectId = parseInt(projectId, 10)
-  assert.integer(projectId, 'bad projectId')
   assert.blobHash(hash, 'bad hash')
 
   const binaryHash = hashToBuffer(hash)
@@ -35,8 +35,8 @@ async function findBlob(projectId, hash) {
  * @return {Promise.<Array.<Blob?>>} no guarantee on order
  */
 async function findBlobs(projectId, hashes) {
+  assert.postgresId(projectId, `bad projectId ${projectId}`)
   projectId = parseInt(projectId, 10)
-  assert.integer(projectId, 'bad projectId')
   assert.array(hashes, 'bad hashes: not array')
   hashes.forEach(function (hash) {
     assert.blobHash(hash, 'bad hash')
@@ -57,8 +57,8 @@ async function findBlobs(projectId, hashes) {
  * Return metadata for all blobs in the given project
  */
 async function getProjectBlobs(projectId) {
+  assert.postgresId(projectId, `bad projectId ${projectId}`)
   projectId = parseInt(projectId, 10)
-  assert.integer(projectId, 'bad projectId')
 
   const records = await knex('project_blobs')
     .select('hash_bytes', 'byte_length', 'string_length')
@@ -103,8 +103,8 @@ async function getProjectBlobsBatch(projectIds) {
  * Add a blob's metadata to the blobs table after it has been uploaded.
  */
 async function insertBlob(projectId, blob) {
+  assert.postgresId(projectId, `bad projectId ${projectId}`)
   projectId = parseInt(projectId, 10)
-  assert.integer(projectId, 'bad projectId')
 
   await knex('project_blobs')
     .insert(blobToRecord(projectId, blob))
@@ -116,8 +116,8 @@ async function insertBlob(projectId, blob) {
  * Deletes all blobs for a given project
  */
 async function deleteBlobs(projectId) {
+  assert.postgresId(projectId, `bad projectId ${projectId}`)
   projectId = parseInt(projectId, 10)
-  assert.integer(projectId, 'bad projectId')
 
   await knex('project_blobs').where('project_id', projectId).delete()
 }

+ 42 - 0
services/history-v1/test/acceptance/js/storage/blob_store_postgres.test.js

@@ -0,0 +1,42 @@
+const postgresBackend = require('../../../../storage/lib/blob_store/postgres')
+const { ObjectId } = require('mongodb')
+const { expect } = require('chai')
+
+describe('BlobStore postgres backend', function () {
+  describe('projectId validation', function () {
+    it('insertBlob rejects when called with bad projectId', async function () {
+      const projectId = new ObjectId().toString()
+      await expect(
+        postgresBackend.insertBlob(projectId, 'hash', 123, 99)
+      ).to.be.rejectedWith(`bad projectId ${projectId}`)
+    })
+
+    it('deleteBlobs rejects when called with bad projectId', async function () {
+      const projectId = new ObjectId().toString()
+      await expect(postgresBackend.deleteBlobs(projectId)).to.be.rejectedWith(
+        `bad projectId ${projectId}`
+      )
+    })
+
+    it('findBlobs rejects when called with bad projectId', async function () {
+      const projectId = new ObjectId().toString()
+      await expect(postgresBackend.findBlobs(projectId)).to.be.rejectedWith(
+        `bad projectId ${projectId}`
+      )
+    })
+
+    it('findBlob rejects when called with bad projectId', async function () {
+      const projectId = new ObjectId().toString()
+      await expect(
+        postgresBackend.findBlob(projectId, 'hash')
+      ).to.be.rejectedWith(`bad projectId ${projectId}`)
+    })
+
+    it('getProjectBlobs rejects when called with bad projectId', async function () {
+      const projectId = new ObjectId().toString()
+      await expect(
+        postgresBackend.getProjectBlobs(projectId)
+      ).to.be.rejectedWith(`bad projectId ${projectId}`)
+    })
+  })
+})