itsapi/github-listener

View on GitHub
src/parser.js

Summary

Maintainability
C
1 day
Test Coverage
A
100%
var qs = require('querystring'),
    util = require('util'),
    crypto = require('crypto');


var Parser = function (data, headers, config) {
  this.body = data;
  this.headers = headers;
  this.config = config;
  this.data = {};
  this.payload = {};

  this.check_url_secret = function () {
    return !this.config.url_secret || this.headers.url_secret === this.config.url_secret;
  };
};

var GitHub = (function () {
  var gh_parser = function () { Parser.apply(this, arguments); };
  util.inherits(gh_parser, Parser);

  gh_parser.prototype.parse_body = function () {
    try { return (this.payload = JSON.parse(this.body)); }
    catch (e) { return undefined; }
  };

  gh_parser.prototype.verify_signature = function () {
    var signature = 'sha1=' + crypto.createHmac('sha1', this.config.github_secret)
                    .update(this.body)
                    .digest('hex');
    return this.headers['x-hub-signature'] === signature && this.check_url_secret();
   };

  gh_parser.prototype.extract = function () {
    if (!(this.payload.repository &&
          this.payload.repository.full_name &&
          this.payload.ref)) {
      return undefined;
    }

    return (this.data = {
      slug:   this.payload.repository.full_name,
      branch: this.payload.ref.replace(/^refs\/heads\//, ''),
      url:    this.payload.repository.url,
      commit: this.payload.head_commit ? this.payload.head_commit.message : undefined,
      image:  this.payload.sender ? this.payload.sender.avatar_url : undefined
    });
  };

  return gh_parser;
})();

var GitLab = (function () {
  var gl_parser = function () { Parser.apply(this, arguments); };
  util.inherits(gl_parser, Parser);

  gl_parser.prototype.parse_body = function () {
    try { return (this.payload = JSON.parse(this.body)); }
    catch (e) { return undefined; }
  };

  gl_parser.prototype.verify_signature = function () {
    return true;
   };

  gl_parser.prototype.extract = function () {
    if (!(this.payload.repository &&
          this.payload.repository.git_ssh_url &&
          this.payload.repository.homepage &&
          this.payload.ref &&
          this.payload.total_commits_count &&
          this.payload.commits)) {
      return undefined;
    }

    var slug = this.payload.repository.git_ssh_url.split(':')[1];
    if (slug.endsWith('.git')) {
      slug = slug.slice(0,-4);
    }

    return (this.data = {
      slug:    slug,
      branch:  this.payload.ref.replace(/^refs\/heads\//, ''),
      url:     this.payload.repository.homepage,
      get_url: this.payload.repository.git_ssh_url.split(':')[0],
      commit:  this.payload.total_commits_count > 0 ? this.payload.commits.slice(-1).message : undefined
    });
  };

  return gl_parser;
})();

var Travis = (function () {
  var travis_parser = function () { Parser.apply(this, arguments); };
  util.inherits(travis_parser, Parser);

  travis_parser.prototype.parse_body = function () {
    try {
      this.body = qs.parse(this.body.toString()).payload;
      return (this.payload = JSON.parse(this.body));
    } catch (e) {
      return undefined;
    }
  };

  travis_parser.prototype.verify_signature = function () {
    if (!(this.headers['signature'] && this.config.travis_public_key)) {
      return false;
    }

    var signature = new Buffer(this.headers['signature'], 'base64');
    var verified = crypto.createVerify('sha1')
                    .update(this.body)
                    .verify(this.config.travis_public_key, signature);

    return verified && this.check_url_secret();
  };

  travis_parser.prototype.extract = function () {
    if (!(this.headers['travis-repo-slug'] && this.payload.branch)) {
      return undefined;
    }

    return (this.data = {
      slug:   this.headers['travis-repo-slug'],
      branch: this.payload.branch,
      commit: this.payload.message,
      url:    this.payload.repository ? this.payload.repository.url : undefined
    });
  };

  return travis_parser;
})();


module.exports = {
  GitHub: GitHub,
  GitLab: GitLab,
  Travis: Travis
};