| /** |
| * Copyright 2014 IBM Corp. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| **/ |
| |
| var should = require("should"); |
| var sinon = require('sinon'); |
| var request = require('supertest'); |
| var http = require('http'); |
| var express = require('express'); |
| |
| var fs = require('fs-extra'); |
| var path = require('path'); |
| var when = require('when'); |
| |
| var app = express(); |
| var RED = require("../../red/red.js"); |
| var server = require("../../red/server.js"); |
| var nodes = require("../../red/nodes"); |
| |
| describe("library", function() { |
| var userDir = path.join(__dirname,".testUserHome"); |
| before(function(done) { |
| fs.remove(userDir,function(err) { |
| fs.mkdir(userDir,function() { |
| sinon.stub(nodes, 'load', function() { |
| return when.promise(function(resolve,reject){ |
| resolve([]); |
| }); |
| }); |
| RED.init(http.createServer(function(req,res){app(req,res)}), |
| {userDir: userDir}); |
| server.start().then(function () { done(); }); |
| }); |
| }); |
| }); |
| |
| after(function(done) { |
| fs.remove(userDir,done); |
| server.stop(); |
| nodes.load.restore(); |
| }); |
| |
| afterEach(function(done) { |
| fs.remove(userDir,function(err) { |
| fs.mkdir(userDir,done); |
| }); |
| }); |
| |
| describe("flows", function() { |
| it('returns empty result', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/flows') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| res.body.should.not.have.property('f'); |
| done(); |
| }); |
| }); |
| |
| it('returns 404 for non-existent entry', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/flows/foo') |
| .expect(404) |
| .end(done); |
| }); |
| |
| it('can store and retrieve item', function(done) { |
| var flow = '[]'; |
| request(RED.httpAdmin) |
| .post('/library/flows/foo') |
| .set('Content-Type', 'text/plain') |
| .send(flow) |
| .expect(204).end(function (err, res) { |
| if (err) { |
| throw err; |
| } |
| request(RED.httpAdmin) |
| .get('/library/flows/foo') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| res.text.should.equal(flow); |
| done(); |
| }); |
| }); |
| }); |
| |
| it('lists a stored item', function(done) { |
| request(RED.httpAdmin) |
| .post('/library/flows/bar') |
| .expect(204) |
| .end(function () { |
| request(RED.httpAdmin) |
| .get('/library/flows') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| res.body.should.have.property('f'); |
| should.deepEqual(res.body.f,['bar']); |
| done(); |
| }); |
| }); |
| }); |
| |
| it('returns 403 for malicious access attempt', function(done) { |
| // without the userDir override the malicious url would be |
| // http://127.0.0.1:1880/library/flows/../../package to |
| // obtain package.json from the node-red root. |
| request(RED.httpAdmin) |
| .get('/library/flows/../../../../../package') |
| .expect(403) |
| .end(done); |
| }); |
| |
| it('returns 403 for malicious access attempt', function(done) { |
| // without the userDir override the malicious url would be |
| // http://127.0.0.1:1880/library/flows/../../package to |
| // obtain package.json from the node-red root. |
| request(RED.httpAdmin) |
| .post('/library/flows/../../../../../package') |
| .expect(403) |
| .end(done); |
| }); |
| |
| }); |
| |
| describe("type", function() { |
| before(function() { |
| RED.library.register('test'); |
| }); |
| |
| it('returns empty result', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/test') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| res.body.should.not.have.property('f'); |
| done(); |
| }); |
| }); |
| |
| it('returns 404 for non-existent entry', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/test/foo') |
| .expect(404) |
| .end(done); |
| }); |
| |
| it('can store and retrieve item', function(done) { |
| var flow = '[]'; |
| request(RED.httpAdmin) |
| .post('/library/test/foo') |
| .set('Content-Type', 'text/plain') |
| .send(flow) |
| .expect(204).end(function (err, res) { |
| if (err) { |
| throw err; |
| } |
| request(RED.httpAdmin) |
| .get('/library/test/foo') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| res.text.should.equal(flow); |
| done(); |
| }); |
| }); |
| }); |
| |
| it('lists a stored item', function(done) { |
| request(RED.httpAdmin) |
| .post('/library/test/bar') |
| .expect(204) |
| .end(function () { |
| request(RED.httpAdmin) |
| .get('/library/test') |
| .expect(200) |
| .end(function(err,res) { |
| if (err) { |
| throw err; |
| } |
| should.deepEqual(res.body,[{ fn: 'bar'}]); |
| done(); |
| }); |
| }); |
| }); |
| |
| |
| it('returns 403 for malicious access attempt', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/test/../../../../../../../../../../etc/passwd') |
| .expect(403) |
| .end(done); |
| }); |
| |
| it('returns 403 for malicious access attempt', function(done) { |
| request(RED.httpAdmin) |
| .get('/library/test/..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\etc\\passwd') |
| .expect(403) |
| .end(done); |
| }); |
| |
| it('returns 403 for malicious access attempt', function(done) { |
| request(RED.httpAdmin) |
| .post('/library/test/../../../../../../../../../../etc/passwd') |
| .set('Content-Type', 'text/plain') |
| .send('root:x:0:0:root:/root:/usr/bin/tclsh') |
| .expect(403) |
| .end(done); |
| }); |
| |
| }); |
| }); |