Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 438a0d64aa3b4e46d7dd7ed1fcf68b18df80d394 1 parent c2e9a77
@timoxley authored
View
17 README.md
@@ -1,4 +1,19 @@
node-webhooks
=============
-easily create webhooks
+## Easily Create Webhooks
+
+1. Create executable script called `webhook` in the directory you wish to
+ run it from.
+2. Run `webhooks` command in same directory as `webhook` executable to
+ get the webhook key.
+3. Boot webhooks with `webhooks start`
+4. Hit webhook via your browser using your webhook key, e.g.
+ http://localhost:10010/CrfYl8CssJ7Jo0dYryVJYMV44CC5AcLi0At%2FF0DXa5TTiSQs%3D
+
+### Security
+
+Use this with much caution. I wouldn't use this on a production
+machine. For increased security, set an environment var
+WH_SECRET=mysecret when running `webhook` or `webhook start` to encrypt
+using a custom keyphrase.
View
11 bin/webhooks
@@ -0,0 +1,11 @@
+#!/usr/bin/env node
+'use strict'
+
+var app = require('../')
+
+if (process.argv[2] === 'start') {
+ var port = process.argv[3] || 10010
+ app.listen(port)
+} else {
+ console.info(app.hashCwd())
+}
View
3  examples/simple/webhook
@@ -0,0 +1,3 @@
+#!/bin/sh
+touch it_worked
+date >> it_worked
View
75 index.js
@@ -0,0 +1,75 @@
+'use strict'
+
+var express = require('express')
+var app = express()
+app.use(express.errorHandler())
+app.use(express.logger())
+var crypto = require('crypto')
+var assert = require('assert')
+var domain = require('domain')
+var fs = require('fs')
+var child_process = require('child_process')
+
+app.get('/:hash', function(req, res, next) {
+ if (!req.params.hash) {
+ console.warn('missing hash', req.params.hash)
+ return res.send(404)
+ }
+ var decryptionKey = process.env.WH_SECRET || 'keyboard cat'
+ try {
+ var dir = decrypt(req.params.hash, decryptionKey)
+ } catch (err) {
+ if (err+''.match(/DecipherFinal/)) {
+ console.warn('could not decipher', req.params.hash)
+ return res.send(404)
+ } else {
+ return next(err)
+ }
+ }
+ fs.exists(dir, function(exists) {
+ if (!exists) {
+ console.warn('directory does not exist!', dir)
+ return res.send(404)
+ }
+ console.info(dir)
+ child_process.exec(module.exports.command, {
+ cwd: dir
+ }, function(err) {
+ if (err) return next(err)
+ res.send(200)
+ })
+ })
+})
+
+var getId = function() {
+ os.hostname() + process.cwd()
+}
+
+module.exports = app
+
+var ALGORITHM = 'cast5-cbc'
+var FORMAT = 'base64'
+
+var encrypt = module.exports.encrypt = function(id, password) {
+ assert.ok(id)
+ assert.ok(password)
+ var projectCipher = crypto.createCipher(ALGORITHM, password)
+ var final = projectCipher.update(id, 'utf8', FORMAT)
+ final += projectCipher.final(FORMAT)
+ return final
+}
+
+var decrypt = module.exports.decrypt = function(encrypted, password) {
+ assert.ok(encrypted)
+ assert.ok(password)
+ var projectDecipher = crypto.createDecipher(ALGORITHM, password)
+ var final = projectDecipher.update(encrypted, FORMAT, 'utf8')
+ final += projectDecipher.final('utf8')
+ return final
+}
+
+module.exports.hashCwd = function(cwd) {
+ return encodeURIComponent(encrypt(cwd || process.cwd(), process.env.WH_SECRET || 'keyboard cat'))
+}
+
+module.exports.command = './webhook'
View
28 package.json
@@ -0,0 +1,28 @@
+{
+ "name": "webhooks",
+ "version": "0.0.0",
+ "main": "index.js",
+ "bin": {
+ "webhook": "./bin/webhook"
+ },
+ "scripts": {
+ "test": "./node_modules/.bin/mocha test/*_test.js"
+ },
+ "license": "BSD",
+ "dependencies": {
+ "express": "~3.0.0rc3"
+ },
+ "devDependencies": {
+ "supertest": "~0.1.2",
+ "mocha": "~1.3.2"
+ },
+ "description": "Easily create webhooks",
+ "directories": {
+ "test": "test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/timoxley/node-webhooks.git"
+ },
+ "author": "Tim Oxley"
+}
View
47 test/api_test.js
@@ -0,0 +1,47 @@
+var request = require('supertest')
+var app = require('../')
+app.command = 'touch testing.js'
+
+var assert = require('assert')
+var fs = require('fs')
+
+afterEach(function(done) {
+ fs.unlink('/tmp/testing.js', function() {
+ fs.unlink('./testing.js', function() {
+ done()
+ })
+ })
+})
+
+it('decodes hashes to paths', function(done) {
+ var hash = app.hashCwd()
+ request(app)
+ .get('/' + hash)
+ .expect(200, done)
+})
+
+it('decodes other hashes to paths', function(done) {
+ var hash = app.hashCwd('/tmp')
+ request(app)
+ .get('/' + hash)
+ .expect(200, done)
+})
+
+it('404 for invalid hashes', function(done) {
+ request(app)
+ .get('/garbage')
+ .expect(404, done)
+})
+
+it('runs commands at cwd', function(done) {
+ var hash = app.hashCwd('/tmp')
+ request(app)
+ .get('/' + hash)
+ .expect(200, function(err) {
+ assert.ifError(err)
+ fs.exists('/tmp/testing.js', function(exists) {
+ assert.ok(exists)
+ done()
+ })
+ })
+})
View
40 test/hashing_test.js
@@ -0,0 +1,40 @@
+'use strict'
+
+var encrypt = require('../').encrypt
+var decrypt = require('../').decrypt
+var hashCwd = require('../').hashCwd
+var assert = require('assert')
+
+it('can decrypt an encrypted message', function() {
+ var token = '/usr/bin'
+ var password = 'password'
+ var encrypted = encrypt(token, password)
+ assert.ok(encrypted != token)
+ assert.strictEqual(token, decrypt(encrypted, password))
+})
+
+it('can decrypt a "complex" encrypted message', function() {
+ var token = process.cwd()
+ token = 'Users/secoif/sdf'
+ var password = 'password'
+ var encrypted = encrypt(token, password)
+ assert.ok(encrypted != token)
+ assert.strictEqual(token, decrypt(encrypted, password))
+})
+
+it('doesn\'t decrypt garbage messages', function() {
+ var token = '/usr/bin'
+ var password = 'password'
+ var encrypted = encrypt(token, password)
+ assert.throws(function() {
+ decrypt('garbage', password)
+ })
+})
+
+it('getCwdHash encodes cwd()', function() {
+ assert.equal(process.cwd(), decrypt(decodeURIComponent(hashCwd()), 'keyboard cat'))
+})
+
+it('getCwdHash encodes passed in cwd()', function() {
+ assert.equal('/tmp', decrypt(decodeURIComponent(hashCwd('/tmp')), 'keyboard cat'))
+})
Please sign in to comment.
Something went wrong with that request. Please try again.