Merge pull request #11 from overleaf/em-unsigned-urls

Add a "unsignedUrls" option to the GCS persistor
This commit is contained in:
Eric Mc Sween 2020-09-28 15:34:47 -04:00 committed by GitHub
commit 65c5793b48
3 changed files with 35 additions and 7 deletions

View file

@ -293,6 +293,7 @@ GCS authentication is configured automatically via the local service account, or
- `gcs.unlockBeforeDelete`: unlock an event-based hold before deleting. default false (see notes) - `gcs.unlockBeforeDelete`: unlock an event-based hold before deleting. default false (see notes)
- `gcs.deletedBucketSuffix`: if present, copy the object to a bucket with this suffix before deletion (see notes) - `gcs.deletedBucketSuffix`: if present, copy the object to a bucket with this suffix before deletion (see notes)
- `gcs.deleteConcurrency`: when recursively deleting a directory, the maximum number of delete requests that will be used at once (default 50) - `gcs.deleteConcurrency`: when recursively deleting a directory, the maximum number of delete requests that will be used at once (default 50)
- `gcs.unsignedUrls`: For testing - do not sign GCS download URLs
- `gcs.endpoint.apiEndpoint`: For testing - specify a different GCS endpoint to use - `gcs.endpoint.apiEndpoint`: For testing - specify a different GCS endpoint to use
- `gcs.endpoint.apiScheme`: For testing - specify a scheme to use for the GCS endpoint (`http` or `https`) - `gcs.endpoint.apiScheme`: For testing - specify a scheme to use for the GCS endpoint (`http` or `https`)
- `gcs.endpoint.projectId`: For testing - the GCS project ID to supply to the overridden backend - `gcs.endpoint.projectId`: For testing - the GCS project ID to supply to the overridden backend

View file

@ -125,6 +125,14 @@ module.exports = class GcsPersistor extends AbstractPersistor {
} }
async getRedirectUrl(bucketName, key) { async getRedirectUrl(bucketName, key) {
if (this.settings.unsignedUrls) {
// Construct a direct URL to the object download endpoint
// (see https://cloud.google.com/storage/docs/request-endpoints#json-api)
const apiScheme = this.settings.endpoint.apiScheme || 'https://'
const apiEndpoint =
this.settings.endpoint.apiEndpoint || 'storage.googleapis.com'
return `${apiScheme}://${apiEndpoint}/download/storage/v1/b/${bucketName}/o/${key}?alt=media`
}
try { try {
const [url] = await this.storage const [url] = await this.storage
.bucket(bucketName) .bucket(bucketName)

View file

@ -260,16 +260,35 @@ describe('GcsPersistorTests', function () {
describe('getRedirectUrl', function () { describe('getRedirectUrl', function () {
let signedUrl let signedUrl
beforeEach(async function () { describe('with signed URLs', function () {
signedUrl = await GcsPersistor.getRedirectUrl(bucket, key) beforeEach(async function () {
signedUrl = await GcsPersistor.getRedirectUrl(bucket, key)
})
it('should request a signed URL', function () {
expect(GcsFile.getSignedUrl).to.have.been.called
})
it('should return the url', function () {
expect(signedUrl).to.equal(redirectUrl)
})
}) })
it('should request a signed URL', function () { describe('with unsigned URLs', function () {
expect(GcsFile.getSignedUrl).to.have.been.called beforeEach(async function () {
}) GcsPersistor.settings.unsignedUrls = true
GcsPersistor.settings.endpoint = {
apiScheme: 'http',
apiEndpoint: 'custom.endpoint'
}
signedUrl = await GcsPersistor.getRedirectUrl(bucket, key)
})
it('should return the url', function () { it('should return a plain URL', function () {
expect(signedUrl).to.equal(redirectUrl) expect(signedUrl).to.equal(
`http://custom.endpoint/download/storage/v1/b/${bucket}/o/${key}?alt=media`
)
})
}) })
}) })