UNPKG

@webda/core

Version:

Expose API with Lambda

415 lines 17.1 kB
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