Files
speckle-server/packages/server/modules/blobstorage/tests/blobstorage.integration.spec.js
T
Gergő Jedlicska a54fa8c28f Test blob storage (#814)
* feat(server): add server authz pipeline rework first sketch

* feat(server authz): add new server authz middleware poc implementation

* test(server authz): add unittests for the new server authz workflow

* feat(wip rework of fileuploads vs blob storage): add basim impl of separate blob storage service

* feat(fileimport service): refactored file import service to utilize the new asssetstorage service

* refactor(server errors): refactor server errors to use the shared module definitions

Now all the errors inherit from BaseError

* refactor(fileimport service): cleanup after refactor

* feat(frontend fileimports): use the new blob storage for downloading the original file

* refactor(server fileimports): clean up the remnants of S3 storage from file imports

* refactor(server authz): centralize generic authz pipeline configs

* refactor(server blob storage): refactor / rename everything to use the `blob-storage` name

* ci(circleci): add s3 objectstorage environment variables

* ci(circleci): fix missing env variables

* ci(circleci): add minio test container

* ci(circleci): fix minio app startup

* ci(circleci): enable circleci remote docker

* ci(circleci): fix minio startup

* ci(cirleci): detach and wait properly for minio to start

* ci(circleci): revert to additional minio img config, it only fails when the container is stopped ?!

* ci(circleci): disable file uploads

* fix(fileimports): update with blob storage refactor leftovers

* feat(server blob storage): add blob storage graphql api

* refactor(server errors): merge new errors to shared module

* fix(server comments rte): fix import for RTE error

* chore(fileimports): remove node-fetch from dependency

* chore(server): remove body parser dependency

* fix(server blob storage): fix gql api

* fix(frontend): fix fileupload item not loading the new upload status, cause of premature event fire

* feat(server blob storage): fix file size limit and allow for public streams

* Update packages/server/modules/blobstorage/graph/schemas/blobstorage.graphql

Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>

* chore(blobstorage): fix PR review issues

* fix(server): fix import bugs

* test(server): blob storage first test

* test(server blob services): add tests for blob storage services

* test(server blob storage): add service and rest api tests

* test(server blob storage): add server blob storage graphql api tests

* feat(server blob storage): store and make available blob fileHash attribute

* feat(server authz): add fatal failure option to server authz pipeline

Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
2022-06-23 16:35:42 +02:00

133 lines
5.3 KiB
JavaScript

const { Buffer } = require('node:buffer')
const request = require('supertest')
const expect = require('chai').expect
const { beforeEachContext } = require('@/test/hooks')
const { createStream } = require('@/modules/core/services/streams')
const { createToken } = require('@/modules/core/services/tokens')
const { createUser } = require('@/modules/core/services/users')
const { Scopes } = require('@/modules/core/helpers/mainConstants')
describe('Blobs integration @blobstorage', () => {
let app
let token
const user = {
name: 'Baron Von Blubba',
email: 'barron@bubble.bobble',
password: 'bubblesAreMyBlobs'
}
before(async () => {
;({ app } = await beforeEachContext())
user.id = await createUser(user)
;({ token } = await createToken({
userId: user.id,
name: 'test token',
scopes: [Scopes.Streams.Write, Scopes.Streams.Read]
}))
})
it('Uploads from multipart upload', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.attach('blob1', require.resolve('@/readme.md'))
.attach('blob2', require.resolve('@/package.json'))
expect(response.status).to.equal(201)
expect(response.body.uploadResults).to.exist
const uploadResults = response.body.uploadResults
expect(uploadResults).to.have.lengthOf(2)
expect(uploadResults.map((r) => r.uploadStatus)).to.have.members([1, 1])
})
it('Errors for too big files, file is deleted', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.attach('blob1', Buffer.alloc(114_857_601, 'asdf'), 'dummy.blob')
expect(response.body.uploadResults).to.have.lengthOf(1)
const [uploadResult] = response.body.uploadResults
expect(uploadResult.uploadStatus).to.equal(2)
expect(uploadResult.uploadError).to.equal('File size limit reached')
const blob = await request(app)
.get(`/api/stream/${streamId}/blob/${uploadResult.blobId}`)
.set('Authorization', `Bearer ${token}`)
expect(blob.status).to.equal(404)
})
it('Gets blob metadata', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.attach('blob1', Buffer.alloc(100, 'asdf'), 'dummy.blob')
expect(response.status).to.equal(201)
expect(response.body.uploadResults).to.have.lengthOf(1)
const [uploadResult] = response.body.uploadResults
const metadataResult = await request(app)
.get(`/api/stream/${streamId}/blobs`)
.set('Authorization', `Bearer ${token}`)
expect(metadataResult.status).to.equal(200)
expect(metadataResult.body.blobs).to.have.lengthOf(1)
expect(metadataResult.body.blobs[0].id).to.equal(uploadResult.blobId)
})
it('Deletes blob and object metadata', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.attach('blob1', Buffer.alloc(100, 'asdf'), 'dummy.blob')
expect(response.status).to.equal(201)
expect(response.body.uploadResults).to.have.lengthOf(1)
const [uploadResult] = response.body.uploadResults
const deleteResult = await request(app)
.delete(`/api/stream/${streamId}/blob/${uploadResult.blobId}`)
.set('Authorization', `Bearer ${token}`)
expect(deleteResult.status).to.equal(204)
const blob = await request(app)
.get(`/api/stream/${streamId}/blob/${uploadResult.blobId}`)
.set('Authorization', `Bearer ${token}`)
expect(blob.status).to.equal(404)
const metadataResult = await request(app)
.get(`/api/stream/${streamId}/blobs`)
.set('Authorization', `Bearer ${token}`)
expect(metadataResult.status).to.equal(200)
expect(metadataResult.body).to.deep.equal({ blobs: [], cursor: null })
})
it('Gets uploaded blob data', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.attach('blob1', Buffer.alloc(10, 'a'), 'dummy.blob')
expect(response.body.uploadResults).to.have.lengthOf(1)
const [uploadResult] = response.body.uploadResults
const blob = await request(app)
.get(`/api/stream/${streamId}/blob/${uploadResult.blobId}`)
.set('Authorization', `Bearer ${token}`)
expect(blob.status).to.equal(200)
expect(blob.headers['content-disposition']).to.equal(
'attachment; filename="dummy.blob"'
)
expect(blob.body.toString()).to.equal('a'.repeat(10))
})
it('Returns 400 for bad form data', async () => {
const streamId = await createStream({ ownerId: user.id })
const response = await request(app)
.post(`/api/stream/${streamId}/blob`)
.set('Authorization', `Bearer ${token}`)
.set('Content-type', 'multipart/form-data; boundary=XXX')
// sending an unfinished part
.send('--XXX\r\nCon')
expect(response.status).to.equal(400)
})
})