diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..75cf8a1 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,10 @@ +engines: + eslint: + enabled: true + channel: "eslint-3" + config: + config: ".eslintrc.json" + +ratings: + paths: + - "**.js" diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 4427bf4..0000000 --- a/.eslintrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "env": { - "node": true - }, - "rules": { - "dot-notation": 2, - "indent": [2, 4, {"SwitchCase": 1}], - "one-var": [2, "never"], - "no-trailing-spaces": [2, { "skipBlankLines": false }], - "keyword-spacing": [2, { - "overrides": { }, - before: true, - after: true - }], - "no-delete-var": 2, - "no-label-var": 2, - "no-shadow": 2, - "no-unused-vars": [ 1, { "args": "none" }] - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..af59f37 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "env": { + "node": true, + "mocha": true + }, + "extends": "eslint:recommended", + "installedESLint": true, + "root": true, + "rules": { + "comma-dangle": [2, "only-multiline"], + "dot-notation": 2, + "indent": [2, 2, {"SwitchCase": 1}], + "one-var": [2, "never"], + "no-trailing-spaces": [2, { "skipBlankLines": false }], + "keyword-spacing": [2, { + "before": true, + "after": true + }], + "no-delete-var": 2, + "no-label-var": 2, + "no-shadow": 2, + "no-unused-vars": [ 1, { "args": "none" }], + "no-console": 0 + } +} diff --git a/.travis.yml b/.travis.yml index fbf165f..444ac5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ script: after_success: - npm install istanbul codecov - - ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -R spec + - npm run coverage - ./node_modules/.bin/codecov sudo: false diff --git a/index.js b/index.js index 92b941a..23fb67c 100644 --- a/index.js +++ b/index.js @@ -7,100 +7,100 @@ var log = '/var/log/haraka.log'; var plugin; exports.register = function () { - plugin = this; - plugin.get_logreader_ini(); - plugin.load_karma_ini(); + plugin = this; + plugin.get_logreader_ini(); + plugin.load_karma_ini(); }; exports.hook_init_http = function (next, server) { - server.http.app.use('/logs/:uuid', exports.get_logs); - server.http.app.use('/karma/rules', exports.get_rules); - return next(); + server.http.app.use('/logs/:uuid', exports.get_logs); + server.http.app.use('/karma/rules', exports.get_rules); + return next(); }; exports.get_logreader_ini = function () { - plugin = this; - plugin.cfg = plugin.config.get('log.reader.ini', function () { - plugin.get_logreader_ini(); - }); + plugin = this; + plugin.cfg = plugin.config.get('log.reader.ini', function () { + plugin.get_logreader_ini(); + }); - if (plugin.cfg.log && plugin.cfg.log.file) { - log = plugin.cfg.log.file; - } + if (plugin.cfg.log && plugin.cfg.log.file) { + log = plugin.cfg.log.file; + } }; exports.load_karma_ini = function () { - plugin.karma_cfg = plugin.config.get('karma.ini', function () { - plugin.load_karma_ini(); - }); + plugin.karma_cfg = plugin.config.get('karma.ini', function () { + plugin.load_karma_ini(); + }); - if (!plugin.karma_cfg.result_awards) return; - if (!plugin.result_awards) plugin.result_awards = {}; + if (!plugin.karma_cfg.result_awards) return; + if (!plugin.result_awards) plugin.result_awards = {}; - Object.keys(plugin.karma_cfg.result_awards).forEach(function (anum) { - var parts = plugin.karma_cfg.result_awards[anum] + Object.keys(plugin.karma_cfg.result_awards).forEach(function (anum) { + var parts = plugin.karma_cfg.result_awards[anum] .replace(/\s+/, ' ') .split(/(?:\s*\|\s*)/); - plugin.result_awards[anum] = { - pi_name : parts[0], - property : parts[1], - operator : parts[2], - value : parts[3], - award : parts[4], - reason : parts[5], - resolution : parts[6], - }; - }); + plugin.result_awards[anum] = { + pi_name : parts[0], + property : parts[1], + operator : parts[2], + value : parts[3], + award : parts[4], + reason : parts[5], + resolution : parts[6], + }; + }); }; exports.get_rules = function (req, res) { - res.send(JSON.stringify(plugin.result_awards)); + res.send(JSON.stringify(plugin.result_awards)); }; exports.get_logs = function (req, res) { - var uuid = req.params.uuid; - if (!/\-/.test(uuid)) { - return res.send('Invalid Request'); - } - if (!/^[0-9A-F\-\.]{12,40}$/.test(uuid)) { - return res.send('Invalid Request'); - } + var uuid = req.params.uuid; + if (!/\-/.test(uuid)) { + return res.send('Invalid Request'); + } + if (!/^[0-9A-F\-\.]{12,40}$/.test(uuid)) { + return res.send('Invalid Request'); + } - var matched = ''; + var matched = ''; // spawning a grep process is quite a lot faster than fs.read // (yes, I benchmarked it) - var child = spawn('grep', [ uuid, log ]); - child.stdout.on('data', function (buffer) { - matched += buffer.toString(); + var child = spawn('grep', [ uuid, log ]); + child.stdout.on('data', function (buffer) { + matched += buffer.toString(); + }); + + child.stdout.on('end', function (err) { + if (err) return res.send('

' + err + '

'); + + var rawLogs = ''; + var lastKarmaLine; + matched.split('\n').forEach(function (line) { + var trimmed = line.replace(/[A-F0-9\-\.]{12,40}/, '$UUID'); + rawLogs += trimmed + '
'; + if (/\[karma/.test(line) && /awards/.test(line)) { + lastKarmaLine = line; + } }); - child.stdout.on('end', function (err) { - if (err) return res.send('

' + err + '

'); - - var rawLogs = ''; - var lastKarmaLine; - matched.split('\n').forEach(function (line) { - var trimmed = line.replace(/[A-F0-9\-\.]{12,40}/, '$UUID'); - rawLogs += trimmed + '
'; - if (/\[karma/.test(line) && /awards/.test(line)) { - lastKarmaLine = line; - } - }); - - var awardNums = []; - if (lastKarmaLine) { - var bits = lastKarmaLine.match(/awards: ([0-9,]+)?\s*/); - if (bits && bits[1]) awardNums = bits[1].split(','); - } - var awards = getAwards(awardNums); - var resolv = getResolutions(awardNums); - - var head = htmlHead(); - var body = htmlBody(uuid, awards.join(''), resolv.join('')); - res.send(head + body + rawLogs + ''); - }); + var awardNums = []; + if (lastKarmaLine) { + var bits = lastKarmaLine.match(/awards: ([0-9,]+)?\s*/); + if (bits && bits[1]) awardNums = bits[1].split(','); + } + var awards = getAwards(awardNums); + var resolv = getResolutions(awardNums); + + var head = htmlHead(); + var body = htmlBody(uuid, awards.join(''), resolv.join('')); + res.send(head + body + rawLogs + ''); + }); }; // exports.grepWithFs = function (file, regex, done) { @@ -118,46 +118,46 @@ exports.get_logs = function (req, res) { // }; function getAwards (awardNums) { - if (!awardNums || awardNums.length === 0) return []; - - var awards = []; - awardNums.forEach(function (a) { - if (!a || !plugin.result_awards[a]) return; - plugin.result_awards[a].id = a; - awards.push(plugin.result_awards[a]); - }); - - var listItems = []; - awards.sort(sortByAward).forEach(function (a) { - var start = '
  • ' + a.award + ', '; - if (a.reason) { - listItems.push(start + a.reason + ' (' + a.value + ')
  • '); - return; - } - listItems.push(start + a.pi_name + ' ' + a.property + + if (!awardNums || awardNums.length === 0) return []; + + var awards = []; + awardNums.forEach(function (a) { + if (!a || !plugin.result_awards[a]) return; + plugin.result_awards[a].id = a; + awards.push(plugin.result_awards[a]); + }); + + var listItems = []; + awards.sort(sortByAward).forEach(function (a) { + var start = '
  • ' + a.award + ', '; + if (a.reason) { + listItems.push(start + a.reason + ' (' + a.value + ')
  • '); + return; + } + listItems.push(start + a.pi_name + ' ' + a.property + ' ' + a.value + ''); - }); - return listItems; + }); + return listItems; } function getResolutions (awardNums) { - if (!awardNums || awardNums.length === 0) return []; - - var awards = []; - awardNums.forEach(function (a) { - if (!a || !plugin.result_awards[a]) return; - awards.push(plugin.result_awards[a]); - }); - - var listItems = []; - var resolutionSeen = {}; - awards.sort(sortByAward).forEach(function (a) { - if (!a.resolution) return; - if (resolutionSeen[a.resolution]) return; - resolutionSeen[a.resolution] = true; - listItems.push('
  • ' + a.resolution + '
  • '); - }); - return listItems; + if (!awardNums || awardNums.length === 0) return []; + + var awards = []; + awardNums.forEach(function (a) { + if (!a || !plugin.result_awards[a]) return; + awards.push(plugin.result_awards[a]); + }); + + var listItems = []; + var resolutionSeen = {}; + awards.sort(sortByAward).forEach(function (a) { + if (!a.resolution) return; + if (resolutionSeen[a.resolution]) return; + resolutionSeen[a.resolution] = true; + listItems.push('
  • ' + a.resolution + '
  • '); + }); + return listItems; } // function grepWithShell (file, string, done) { @@ -169,14 +169,14 @@ function getResolutions (awardNums) { // } function sortByAward (a, b) { - if (parseFloat(b.award) > parseFloat(a.award)) return -1; - if (parseFloat(b.award) < parseFloat(a.award)) return 1; - return 0; + if (parseFloat(b.award) > parseFloat(a.award)) return -1; + if (parseFloat(b.award) < parseFloat(a.award)) return 1; + return 0; } function htmlHead () { /* jshint multistr: true */ - var str = ' \ + var str = ' \ \ \ \ @@ -185,32 +185,32 @@ function htmlHead () { div { padding: 1em; } \ \ '; - return str; + return str; } function htmlBody (uuid, awards, resolve) { /* jshint multistr: true */ - var str = ' \ + var str = ' \
    \

    Sorry we blocked your message:

    \

    Our filters mistook your server for a malicious computer attempting \ to send spam. To improve your mail servers reputation, please contact \ your IT helpdesk or Systems Administrator and ask them for help.

    '; - if (awards) { - str += '

    Policy Rules

    \ + if (awards) { + str += '

    Policy Rules

    \ '; - } + } - if (resolve) { - str += '

    Steps to Resolve

    \ + if (resolve) { + str += '

    Steps to Resolve

    \ '; - } + } - str += '
    \ + str += '
    \

    Raw Logs

    \

    ' + uuid + '

    \
     \
             \n';
    -    return str;
    +  return str;
     }
    diff --git a/package.json b/package.json
    index 16a6970..2b3c82f 100644
    --- a/package.json
    +++ b/package.json
    @@ -1,11 +1,12 @@
     {
       "name": "haraka-plugin-log-reader",
    -  "version": "1.0.2",
    +  "version": "1.0.3",
       "description": "display log entries from haraka log files via HTTP",
       "main": "index.js",
       "scripts": {
    -    "test": "mocha",
    -    "lint": "node node_modules/.bin/eslint *.js test/*.js"
    +    "test": "./node_modules/.bin/mocha",
    +    "lint": "./node_modules/.bin/eslint *.js test",
    +    "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha"
       },
       "repository": {
         "type": "git",
    diff --git a/test/index.js b/test/index.js
    index 86649ff..f58f1b1 100644
    --- a/test/index.js
    +++ b/test/index.js
    @@ -9,58 +9,58 @@ var assert   = require('assert');
     var fixtures = require('haraka-test-fixtures');
     
     describe('register', function () {
    -    var attach = new fixtures.plugin('index');
    +  var attach = new fixtures.plugin('index');
     
    -    it('is a function', function (done) {
    -        assert.equal('function', typeof attach.register);
    -        done();
    -    });
    +  it('is a function', function (done) {
    +    assert.equal('function', typeof attach.register);
    +    done();
    +  });
     
    -    it('runs', function (done) {
    -        attach.register();
    +  it('runs', function (done) {
    +    attach.register();
             // console.log(attach.cfg);
    -        done();
    -    });
    +    done();
    +  });
     
    -    it('loads log.reader.ini', function (done) {
    -        attach.register();
    -        assert.deepEqual(attach.cfg, {
    -            main: {},
    -            log: {
    -                file: '/var/log/haraka.log'
    -            }
    -        });
    -        done();
    +  it('loads log.reader.ini', function (done) {
    +    attach.register();
    +    assert.deepEqual(attach.cfg, {
    +      main: {},
    +      log: {
    +        file: '/var/log/haraka.log'
    +      }
         });
    +    done();
    +  });
     
    -    it('loads karma.ini', function (done) {
    -        attach.register();
    -        assert.equal(attach.karma_cfg.tarpit.delay, 0);
    -        done();
    -    });
    +  it('loads karma.ini', function (done) {
    +    attach.register();
    +    assert.equal(attach.karma_cfg.tarpit.delay, 0);
    +    done();
    +  });
     });
     
     describe('log.reader.ini', function () {
    -    var reader = new fixtures.plugin('index');
    +  var reader = new fixtures.plugin('index');
     
    -    it('has a log section', function (done) {
    -        reader.register();
    -        assert.ok(reader.cfg.log.file);
    -        done();
    -    });
    +  it('has a log section', function (done) {
    +    reader.register();
    +    assert.ok(reader.cfg.log.file);
    +    done();
    +  });
     });
     
     // the subsequent functions require the express res/req
     // those could be mocked up, along with some sample log files
     
     describe('get_logs', function() {
    -    it.skip('reads entries from a log file', function (done) {
    -        done();
    -    })
    +  it.skip('reads entries from a log file', function (done) {
    +    done();
    +  })
     });
     
     describe('get_rules', function() {
    -    it.skip('returns rules section from karma.ini', function (done) {
    -        done();
    -    })
    +  it.skip('returns rules section from karma.ini', function (done) {
    +    done();
    +  })
     });
    diff --git a/test/mocha.opts b/test/mocha.opts
    new file mode 100644
    index 0000000..5ada47b
    --- /dev/null
    +++ b/test/mocha.opts
    @@ -0,0 +1 @@
    +--reporter spec