diff --git a/__mocks__/bent.js b/__mocks__/bent.js new file mode 100644 index 0000000..e3a3591 --- /dev/null +++ b/__mocks__/bent.js @@ -0,0 +1,13 @@ +const fs = require('fs-extra'); +const tar = require('tar'); +const path = require('path'); + +module.exports = () => async () => { + const root = path.resolve(__dirname, 'user-installable-package'); + const files = await fs.readdir(root); + + return tar.c({ + gzip: true, + cwd: root + }, files); +}; diff --git a/__mocks__/user-installable-package/metadata.json b/__mocks__/user-installable-package/metadata.json new file mode 100644 index 0000000..455dabd --- /dev/null +++ b/__mocks__/user-installable-package/metadata.json @@ -0,0 +1,3 @@ +{ + "name": "UserInstallablePackage" +} diff --git a/__tests__/packages.js b/__tests__/packages.js index 940c477..bbb7644 100644 --- a/__tests__/packages.js +++ b/__tests__/packages.js @@ -2,6 +2,8 @@ const osjs = require('osjs'); const path = require('path'); const Packages = require('../src/packages.js'); +jest.mock('bent'); + describe('Packages', () => { let core; let packages; @@ -25,6 +27,22 @@ describe('Packages', () => { .toBe(true); }); + test('#installPackage', async () => { + await expect(packages.installPackage('jest:/UserInstallablePackage.tgz?redacted', { + root: 'home:/.packages' + }, {username: 'packages'})).resolves.toEqual({ + reload: true + }); + }); + + test('#uninstallPackage', async () => { + await expect(packages.uninstallPackage('UserInstallablePackage', { + root: 'home:/.packages' + }, {username: 'packages'})).resolves.toEqual({ + reload: true + }); + }); + test('#handleMessage', () => { const params = [{ pid: 1, diff --git a/src/packages.js b/src/packages.js index bf5a32b..e2870c4 100644 --- a/src/packages.js +++ b/src/packages.js @@ -159,18 +159,22 @@ class Packages { const name = archiveName(url); const target = await realpath(`${options.root}/${name}`, user); - if (await fs.exists(target)) { + if (path.resolve(target) === path.resolve(options.root)) { + throw new Error('Invalid package source'); + } else if (await fs.exists(target)) { throw new Error('Target already exists'); } else if (options.system) { throw new Error('System packages not yet implemented'); } const stream = await fetchSteam(url, options); - await fs.mkdir(target); + + await fs.mkdirp(target); await extract(stream, target); // FIXME: npm packages have a 'package' subdirectory - if (!await fs.exists(path.resolve(target, 'metadata.json'))) { + const exists = await fs.exists(path.resolve(target, 'metadata.json')); + if (!exists) { await fs.remove(target); throw new Error('Invalid package');