@webda/core
Version:
Expose API with Lambda
415 lines • 17.1 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 { suite, test } from "@testdeck/mocha";
import * as assert from "assert";
import { EventEmitter } from "events";
import * as fs from "fs";
import { mkdirSync, writeFileSync } from "fs";
import pkg from "fs-extra";
import sinon from "sinon";
import { Readable } from "stream";
import { Core } from "../core.js";
import { WebdaError } from "../errors.js";
import { CoreModel } from "../models/coremodel.js";
import { WebdaTest } from "../test.js";
import { FileUtils } from "../utils/serializers.js";
import { BinariesImpl, BinariesItem, Binary, BinaryFile, BinaryService, MemoryBinaryFile } from "./binary.js";
import { TestBinaryService } from "./binary.spec.js";
import { CloudBinaryTest } from "./cloudbinary.spec.js";
import { FileBinary } from "./filebinary.js";
const { removeSync } = pkg;
class FaultyBinaryFile extends BinaryFile {
async get() {
const stream = new Readable();
stream._read = () => {
stream.emit("error", new Error("Faulty stream"));
};
return stream;
}
}
let FileBinaryTest = class FileBinaryTest extends CloudBinaryTest {
initMap() {
let binary = this.getBinary();
binary.initMap(undefined);
binary.initMap({ _init: true });
// Bad store
binary.initMap({
VersionService: {},
None: {},
MemoryIdents: "idents"
});
}
testEmpty() {
assert.strictEqual(new Binary("test", {}).isEmpty(), true);
assert.strictEqual(new Binary("test", { test: {} }).isEmpty(), false);
}
async _getFile() {
let binary = this.getBinary();
let ctx = await this.newContext();
ctx.getHttpContext().setBody("plop");
ctx.getHttpContext().headers = { "content-type": "text/plain" };
assert.deepStrictEqual(await binary._getFile(ctx), new MemoryBinaryFile(Buffer.from("plop"), {
challenge: undefined,
hash: undefined,
metadata: {},
mimetype: "text/plain",
name: "",
size: 4
}));
}
initRoutes() {
let binary = this.getBinary();
binary.getParameters().expose = undefined;
binary.initRoutes();
// @ts-ignore
binary._name = "Binary";
binary.initRoutes();
}
async downloadSignedUrl() {
let binary = this.getBinary();
let { user1, ctx } = await this.setupDefault(false);
let url = await binary.getRedirectUrlFromObject(user1.images[0], ctx, 60);
assert.notStrictEqual(url, undefined);
await this.execute(ctx, "test.webda.io", "GET", url.substring("http://test.webda.io".length));
// c59d?token -> d59d?token
await assert.rejects(() => this.execute(ctx, "test.webda.io", "GET", url.substring("http://test.webda.io".length).replace("c59d?token", "d59d?token")), WebdaError.Forbidden);
await assert.rejects(() => this.execute(ctx, "test.webda.io", "GET", url.substring("http://test.webda.io".length).replace("eyJhbG", "ezJhbG")), WebdaError.Forbidden);
}
async verifyMapAndStore() {
let binary = this.getBinary();
let ctx = await this.newContext();
ctx.setPathParameters({ store: "Store", property: "images" });
assert.throws(() => binary._verifyMapAndStore(ctx), (err) => err.getResponseCode() === 404);
ctx.setPathParameters({ store: "users", property: "images" });
assert.strictEqual(binary._verifyMapAndStore(ctx), this.getService("Users"));
ctx.setPathParameters({ store: "users", property: "images2" });
assert.throws(() => binary._verifyMapAndStore(ctx), (err) => err.getResponseCode() === 404);
ctx.setPathParameters({ store: "notexisting", property: "images" });
assert.throws(() => binary._verifyMapAndStore(ctx), (err) => err.getResponseCode() === 404);
}
computeParameters() {
let binary = this.getBinary();
removeSync(binary.getParameters().folder);
binary.computeParameters();
assert.ok(fs.existsSync(binary.getParameters().folder));
}
async challenge() {
await this.testChallenge();
}
async badTokens() {
let binary = this.getBinary();
let ctx = await this.newContext();
let { hash } = await new MemoryBinaryFile(Buffer.from("PLOP"), {}).getHashes();
let token = "badt";
ctx.setPathParameters({
hash,
token
});
ctx.getHttpContext().setBody("PLOP");
await assert.rejects(() => binary.storeBinary(ctx), (err) => err.getResponseCode() === 403);
token = await this.webda.getCrypto().jwtSign({ hash: "PLOP2" });
ctx.setPathParameters({
hash,
token
});
await assert.rejects(() => binary.storeBinary(ctx), (err) => err.getResponseCode() === 403);
// expired token
token = await this.webda.getCrypto().jwtSign({ hash, exp: Math.floor(Date.now() / 1000) - 60 * 60 });
ctx.setPathParameters({
hash,
token
});
await assert.rejects(() => binary.storeBinary(ctx), (err) => err.getResponseCode() === 403);
token = await this.webda.getCrypto().jwtSign({ hash });
ctx.setPathParameters({
hash,
token
});
await assert.rejects(() => binary.storeBinary(ctx), (err) => err.getResponseCode() === 412);
}
cleanNonExisting() {
let binary = this.getBinary();
binary._cleanHash("plop");
binary._cleanUsage("plop", "l");
}
faultyBinary() {
const file = new FaultyBinaryFile({
mimetype: "text/plain",
name: "test.txt",
size: 10
});
assert.rejects(() => file.getHashes(), /Faulty stream/);
}
cov() {
let binary = this.getBinary();
try {
binary._touch("./touch.txt");
binary._touch("./touch.txt");
}
finally {
fs.unlinkSync("./touch.txt");
}
}
async handleBinary() {
this.registerService(new FileBinary(Core.get(), "second", {
folder: "./test/data/binaries",
models: {}
}));
const binaries = Core.get().getServicesOfType(BinaryService);
const user = Core.get().getModel("WebdaDemo/User");
assert.strictEqual(Core.get().getBinaryStore(user, "images"), binaries["binary"]);
binaries["binary"].getParameters().models = {};
assert.throws(() => Core.get().getBinaryStore(user, "profilePicture"), /No binary store found for WebdaDemo\/User profilePicture/);
binaries["binary"].getParameters().models = {
"WebdaDemo/User": ["*"]
};
binaries["second"].getParameters().models = {
"WebdaDemo/User": ["profilePicture"]
};
assert.strictEqual(Core.get().getBinaryStore(user, "profilePicture"), binaries["second"]);
}
/**
* Test that we can use binary attributes
*/
async binaryAttributes() {
const user = Core.get().getModel("WebdaDemo/User");
const User = await new user().load({}, true).save();
//User.profilePicture.upload(new MemoryBinaryFile(Buffer.from("PLOP"), <BinaryFileInfo>(<unknown>{})));
await User.profilePicture.upload(new MemoryBinaryFile(Buffer.from("PLOP"), {}));
await User.images.upload(new MemoryBinaryFile(Buffer.from("PLOP2"), {}));
await this.sleep(1000);
let files = FileUtils.find("./test/data/binaries");
assert.deepStrictEqual(files, [
`test/data/binaries/f15c25d20d6b9a631ab6de08cd00035e/MemoryUsers_profilePicture_${User.getUuid()}`,
"test/data/binaries/f15c25d20d6b9a631ab6de08cd00035e/_9eed42d099ec7ef1eed00a49e8079cd2",
"test/data/binaries/f15c25d20d6b9a631ab6de08cd00035e/data",
`test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/MemoryUsers_images_${User.getUuid()}`,
"test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/_0a4ef38590e0bd4a8999f1489186bbe9",
"test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/data"
]);
await User.profilePicture.delete();
await this.sleep(1000);
files = FileUtils.find("./test/data/binaries");
assert.deepStrictEqual(files, [
`test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/MemoryUsers_images_${User.getUuid()}`,
"test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/_0a4ef38590e0bd4a8999f1489186bbe9",
"test/data/binaries/ff1cee367d40cacc3fe5f23e985c29ae/data"
]);
await User.images[0].upload(new MemoryBinaryFile(Buffer.from("0123456789"), {
mimetype: "text/plain",
name: "test.txt",
size: 10
}));
await User.images[0].delete();
await this.sleep(1000);
files = FileUtils.find("./test/data/binaries");
assert.deepStrictEqual(files, []);
}
};
__decorate([
test
], FileBinaryTest.prototype, "initMap", null);
__decorate([
test
], FileBinaryTest.prototype, "testEmpty", null);
__decorate([
test
], FileBinaryTest.prototype, "_getFile", null);
__decorate([
test
], FileBinaryTest.prototype, "initRoutes", null);
__decorate([
test
], FileBinaryTest.prototype, "downloadSignedUrl", null);
__decorate([
test
], FileBinaryTest.prototype, "verifyMapAndStore", null);
__decorate([
test
], FileBinaryTest.prototype, "computeParameters", null);
__decorate([
test
], FileBinaryTest.prototype, "challenge", null);
__decorate([
test
], FileBinaryTest.prototype, "badTokens", null);
__decorate([
test
], FileBinaryTest.prototype, "cleanNonExisting", null);
__decorate([
test
], FileBinaryTest.prototype, "faultyBinary", null);
__decorate([
test
], FileBinaryTest.prototype, "cov", null);
__decorate([
test
], FileBinaryTest.prototype, "handleBinary", null);
__decorate([
test
], FileBinaryTest.prototype, "binaryAttributes", null);
FileBinaryTest = __decorate([
suite
], FileBinaryTest);
let BinaryAbstractTest = class BinaryAbstractTest extends WebdaTest {
async cov() {
let service = new TestBinaryService(undefined, "plop", {});
assert.strictEqual(await service.getRedirectUrlFromObject(undefined, undefined, 60), null);
let ctx = await this.newContext();
await assert.rejects(() => service.putRedirectUrl(undefined), (err) => err.getResponseCode() === 404);
ctx.getHttpContext().setBody({
hash: "plop"
});
await assert.rejects(() => service.httpChallenge(ctx), (err) => err.getResponseCode() === 400);
ctx = await this.newContext();
ctx.getHttpContext().setBody({
challenge: "plop"
});
await assert.rejects(() => service.httpChallenge(ctx), (err) => err.getResponseCode() === 400);
ctx = await this.newContext();
let binary = this.getService("binary");
ctx.setPathParameters({
property: "images",
store: "users",
uid: "notfound",
index: 0
});
ctx.getHttpContext().setBody({
hash: "p",
challenge: "z"
});
await assert.rejects(() => binary.httpChallenge(ctx), (err) => err.getResponseCode() === 404);
let stubs = [];
try {
let model = {
images: [
{
size: 10
}
],
canAct: async () => true,
checkAct: async () => { }
};
stubs.push(sinon.stub(binary, "getRedirectUrlFromObject").callsFake(() => {
return null;
}));
stubs.push(sinon.stub(binary, "_verifyMapAndStore").callsFake(() => {
return {
get: async () => {
return model;
}
};
}));
stubs.push(
// @ts-ignore
sinon.stub(binary, "get").callsFake(async () => {
return Readable.from("PLOP");
}));
await binary.httpGet(ctx);
assert.strictEqual(ctx.getResponseBody().toString(), "PLOP");
stubs[stubs.length - 1].callsFake(async () => {
return {
pipe: stream => {
stream.emit("error", new Error("I/O"));
}
};
});
await assert.rejects(() => binary.httpGet(ctx));
let uri = ctx.getHttpContext().getRelativeUri();
let url = ctx.getHttpContext().getAbsoluteUrl();
ctx.getHttpContext().getRelativeUri = () => uri + "/url";
ctx.getHttpContext().getAbsoluteUrl = () => url + "/url";
await binary.httpGet(ctx);
assert.strictEqual(ctx.getResponseBody(), `{"Location":"http://test.webda.io/","Map":{"size":10}}`);
}
finally {
stubs.forEach(stub => stub.restore());
}
}
async handleBinary() {
const binaryService = this.getService("binary");
assert.strictEqual(binaryService.handleBinary("WebdaDemo/User", "images"), 2);
assert.strictEqual(binaryService.handleBinary("WebdaDemo/User", "profilePicture"), 0);
assert.strictEqual(binaryService.handleBinary("WebdaDemo/User2", "images"), 0);
binaryService.getParameters().models["*"] = ["images"];
assert.strictEqual(binaryService.handleBinary("WebdaDemo/User2", "images"), 1);
assert.strictEqual(binaryService.handleBinary("WebdaDemo/User2", "images2"), -1);
}
async binaryMaps() {
let map = new BinariesImpl().assign(new CoreModel(), "test");
await assert.rejects(() => map.upload(undefined));
await assert.throws(() => map.shift());
await assert.throws(() => map.unshift());
await assert.throws(() => map.slice());
await assert.throws(() => map.pop());
let binary = new Binary("test", new CoreModel());
await assert.rejects(() => binary.upload(undefined));
await assert.rejects(() => binary.delete());
let binaryItem = new BinariesItem(map, new MemoryBinaryFile(Buffer.from("test"), {
name: "test",
mimetype: "text/plain",
size: 4
}));
await assert.rejects(() => binaryItem.upload(undefined));
await assert.rejects(() => binaryItem.delete());
}
async streamToBufferError() {
let stream = new EventEmitter();
// @ts-ignore
let p = assert.rejects(() => BinaryService.streamToBuffer(stream), /Bad I\/O/);
stream.emit("error", new Error("Bad I/O"));
await p;
}
async verifyMapStore() {
const binaryService = this.getService("binary");
const ctx = await this.newContext();
binaryService.handleBinary = () => -1;
ctx.getParameters().model = "webda/test";
assert.throws(() => binaryService._verifyMapAndStore(ctx), WebdaError.NotFound);
}
async putRedirectUrl() {
const binaryService = this.getService("binary");
let ctx = await this.newContext(JSON.stringify({ hash: "123" }));
ctx.getParameters().uuid = "456";
ctx.getParameters().store = "Test";
ctx.getParameters().property = "plop";
let dataPath = binaryService._getPath("123", "data");
mkdirSync(binaryService._getPath("123"), { recursive: true });
writeFileSync(binaryService._getPath("123", "Test_plop_456"), "");
if (fs.existsSync(dataPath)) {
fs.unlinkSync(dataPath);
}
let res = await binaryService.putRedirectUrl(ctx);
assert.notStrictEqual(res, undefined);
writeFileSync(dataPath, "data");
res = await binaryService.putRedirectUrl(ctx);
assert.strictEqual(res, undefined);
}
};
__decorate([
test
], BinaryAbstractTest.prototype, "cov", null);
__decorate([
test
], BinaryAbstractTest.prototype, "handleBinary", null);
__decorate([
test
], BinaryAbstractTest.prototype, "binaryMaps", null);
__decorate([
test
], BinaryAbstractTest.prototype, "streamToBufferError", null);
__decorate([
test
], BinaryAbstractTest.prototype, "verifyMapStore", null);
__decorate([
test
], BinaryAbstractTest.prototype, "putRedirectUrl", null);
BinaryAbstractTest = __decorate([
suite
], BinaryAbstractTest);
export { FileBinaryTest };
//# sourceMappingURL=filebinary.spec.js.map