@webda/aws
Version:
Webda AWS Services implementation
269 lines • 10.2 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { HeadObjectCommand, ListObjectsV2Command, S3 } from "@aws-sdk/client-s3";
import { suite, test } from "@testdeck/mocha";
import { BinaryService, getCommonJS } from "@webda/core";
import { BinaryTest } from "@webda/core/lib/services/binary.spec.js";
import * as assert from "assert";
import { mockClient } from "aws-sdk-client-mock";
import * as path from "path";
import * as sinon from "sinon";
import { checkLocalStack, defaultCreds } from "../index.spec.js";
import { DynamoDBTest } from "./dynamodb.spec.js";
import { S3BinaryParameters } from "./s3binary.js";
const { __dirname } = getCommonJS(import.meta.url);
let S3BinaryTest = class S3BinaryTest extends BinaryTest {
async before() {
process.env.AWS_ACCESS_KEY_ID = defaultCreds.accessKeyId;
process.env.AWS_SECRET_ACCESS_KEY = defaultCreds.secretAccessKey;
await checkLocalStack();
await this.buildWebda();
await this.install();
await this.cleanData();
await DynamoDBTest.install("webda-test-idents");
await DynamoDBTest.install("webda-test-users");
await super.before();
}
async tweakApp(app) {
super.tweakApp(app);
app.addService("test/awsevents", (await import(path.join(__dirname, ..."../../test/moddas/awsevents.js".split("/")))).AWSEventsHandler);
}
// Override getNotFound as exception is raised after
async getNotFound() { }
async cleanData() {
const Bucket = "webda-test";
try {
var s3 = new S3({
endpoint: "http://localhost:4566",
credentials: defaultCreds,
forcePathStyle: true,
region: "us-east-1"
});
// For test we do not have more than 1k objects
let data = await s3.listObjectsV2({
Bucket
});
var params = {
Bucket,
Delete: {
Objects: []
}
};
for (var i in data.Contents) {
params.Delete.Objects.push({
Key: data.Contents[i].Key
});
}
if (params.Delete.Objects.length === 0) {
return;
}
await s3.deleteObjects(params);
}
catch (err) {
// Ignore error for now
}
}
async install() {
var s3 = new S3({
endpoint: "http://localhost:4566",
forcePathStyle: true,
credentials: defaultCreds,
region: "us-east-1"
});
const Bucket = "webda-test";
try {
await s3.headBucket({
Bucket
});
}
catch (err) {
if (err.name === "Forbidden") {
this.webda.log("ERROR", "S3 bucket already exists in another account");
}
else if (err.name === "NotFound") {
this.webda.log("INFO", "Creating S3 Bucket", Bucket);
return s3.createBucket({
Bucket
});
}
}
}
getARN() {
let policies = this.getBinary().getARNPolicy("plop");
assert.strictEqual(policies.Resource[0], "arn:aws:s3:::webda-test");
assert.strictEqual(policies.Resource[1], "arn:aws:s3:::webda-test/*");
this.getBinary().getParameters().CloudFormationSkip = true;
assert.deepStrictEqual(this.getBinary().getCloudFormation(undefined), {});
}
async forEachFile() {
let keys = [];
const spyChanges = sinon.stub().callsFake(async (p, c) => {
if (spyChanges.callCount === 1) {
return {
Contents: [
{ Key: "test/test.txt" },
{ Key: "test/test.json" },
{ Key: "test2/test.txt" },
{ Key: "loop.txt" }
].filter(i => {
return i.Key.startsWith(p.Prefix);
}),
NextContinuationToken: "2"
};
}
return { Contents: [] };
});
const mock = mockClient(S3).on(ListObjectsV2Command).callsFake(spyChanges);
try {
await this.getBinary().forEachFile("myBucket", async (Key) => {
keys.push(Key);
}, undefined, /.*\.txt/);
assert.deepStrictEqual(keys, ["test/test.txt", "test2/test.txt", "loop.txt"]);
keys = [];
spyChanges.resetHistory();
await this.getBinary().forEachFile("myBucket", async (Key) => {
keys.push(Key);
}, "test/");
assert.deepStrictEqual(keys, ["test/test.txt", "test/test.json"]);
}
finally {
mock.restore();
}
}
params() {
assert.throws(() => new S3BinaryParameters({}, this.getBinary()), /Need to define a bucket at least/);
}
async signedUrl() {
let urls = [
this.getBinary().getSignedUrl("plop/test", "putObject", {
Bucket: "myBuck"
}),
this.getBinary().getSignedUrl("plop/test")
];
(await Promise.all(urls)).forEach(url => {
assert.ok(url.match(/http:\/\/localhost:\d+\/(myBuck|webda-test)\/plop\/test\?.*Signature=.*/), `'${url}' does not match expected`);
});
}
async exists() {
assert.ok(!(await this.getBinary()._exists("bouzouf")));
await this.getBinary().putObject(this.getBinary()._getKey("bouzouf"), "plop");
assert.ok(await this.getBinary()._exists("bouzouf"));
assert.strictEqual((await BinaryService.streamToBuffer(await this.getBinary().getObject(this.getBinary()._getKey("bouzouf")))).toString("utf8"), "plop");
assert.notStrictEqual(await this.getBinary().exists(this.getBinary()._getKey("bouzouf")), null);
assert.strictEqual(await this.getBinary().exists(this.getBinary()._getKey("bouzouf2")), null);
}
async cleanHash() {
let key1 = this.getBinary()._getKey("bouzouf", "one");
let key2 = this.getBinary()._getKey("bouzouf", "two");
await this.getBinary().putObject(key1, "plop");
await this.getBinary().putObject(key2, "plop");
await this.getBinary()._cleanHash("bouzouf");
// TO CONTINUE (localstack might not handle V2)
}
getKey() {
let key = this.getBinary()._getKey("bouzouf", "two");
assert.strictEqual(key, "bouzouf/two");
this.getBinary().getParameters().prefix = "plop";
key = this.getBinary()._getKey("bouzouf", "two");
assert.strictEqual(key, "plop/bouzouf/two");
}
async cascadeDelete() {
let stubDelete = sinon.stub(this.getBinary()._s3, "deleteObject").callsFake(() => {
throw new Error();
});
try {
// @ts-ignore
await this.getBinary().cascadeDelete({ hash: "pp" }, "pp");
}
finally {
stubDelete.restore();
}
}
async redirectUrl() {
let { user1, ctx } = await this.setupDefault();
// Making sure we are redirected on GET
let executor = this.getExecutor(ctx, "test.webda.io", "GET", `/binary/users/${user1.getUuid()}/images/0`, {});
await executor.execute(ctx);
assert.ok(ctx.getResponseHeaders().Location !== undefined);
}
async redirectUrlInfo() {
let { user1, ctx } = await this.setupDefault();
// Making sure we are redirected on GET
let executor = this.getExecutor(ctx, "test.webda.io", "GET", `/binary/users/${user1.getUuid()}/images/0/url`, {});
await executor.execute(ctx);
assert.ok(ctx.getResponseHeaders().Location === undefined);
assert.notStrictEqual(JSON.parse(ctx.getResponseBody()).Location, undefined);
}
async httpGetError() {
// GET is not through classic binary
// Skip it
}
async challenge() {
await this.testChallenge(false);
}
async badErrors() {
const mock = mockClient(S3)
.on(HeadObjectCommand)
.callsFake(() => {
throw new Error("Fake");
});
try {
await assert.rejects(() => this.getBinary()._getS3("plop"));
await assert.rejects(() => this.getBinary()._exists("plop"));
await assert.rejects(() => this.getBinary().exists("plop"));
}
finally {
mock.restore();
}
}
};
__decorate([
test
], S3BinaryTest.prototype, "getNotFound", null);
__decorate([
test
], S3BinaryTest.prototype, "getARN", null);
__decorate([
test
], S3BinaryTest.prototype, "forEachFile", null);
__decorate([
test
], S3BinaryTest.prototype, "params", null);
__decorate([
test
], S3BinaryTest.prototype, "signedUrl", null);
__decorate([
test
], S3BinaryTest.prototype, "exists", null);
__decorate([
test
], S3BinaryTest.prototype, "cleanHash", null);
__decorate([
test
], S3BinaryTest.prototype, "getKey", null);
__decorate([
test
], S3BinaryTest.prototype, "cascadeDelete", null);
__decorate([
test
], S3BinaryTest.prototype, "redirectUrl", null);
__decorate([
test
], S3BinaryTest.prototype, "redirectUrlInfo", null);
__decorate([
test
], S3BinaryTest.prototype, "httpGetError", null);
__decorate([
test
], S3BinaryTest.prototype, "challenge", null);
__decorate([
test
], S3BinaryTest.prototype, "badErrors", null);
S3BinaryTest = __decorate([
suite
], S3BinaryTest);
//# sourceMappingURL=s3binary.spec.js.map