Basic Auth - closes #14

pull/16/head
Maciej Winnicki 2013-05-26 11:21:58 +02:00
parent 5d3506b172
commit 987f285ead
6 changed files with 91 additions and 39 deletions

View File

@ -6,6 +6,7 @@ frontail is node.js application for serving `tail -F` output to browser using [s
### Features
* basic auth
* filtering logs (press Tab to focus input)
* terminal-like autoscrolling
* marking logs
@ -20,14 +21,16 @@ frontail is node.js application for serving `tail -F` output to browser using [s
Options:
-h, --help output usage information
-V, --version output the version number
-p, --port <port> server port, default 9001
-n, --number <number> starting lines number, default 10
-l, --lines <number> number on lines stored in frontend, default 2000
-d, --daemonize run as daemon
--pid-path <path> if run as deamon file that will store the process ID, default /var/run/frontail.pid
--log-path <path> if run as deamon file that will be used as a log, default /dev/null
-h, --help output usage information
-V, --version output the version number
-p, --port <port> server port, default 9001
-n, --number <number> starting lines number, default 10
-l, --lines <number> number on lines stored in frontend, default 2000
-d, --daemonize run as daemon
-U, --user <username> Basic Auth user
-P, --password <password> Basic Auth password
--pid-path <path> if run as daemon file that will store the process ID, default /var/run/frontail.pid
--log-path <path> if run as daemon file that will be used as a log, default /dev/null
Web interface is on http://localhost:[port]
@ -39,7 +42,7 @@ Web interface is on http://localhost:[port]
(The MIT License)
Copyright 2012 Maciej Winnicki http://maciejwinnicki.pl
Copyright 2013 Maciej Winnicki http://maciejwinnicki.pl
This project is free software released under the MIT/X11 license:

View File

@ -1,11 +1,12 @@
var program = require('commander')
, http = require('http')
, fs = require('fs')
, socketio = require('socket.io')
, spawn = require('child_process').spawn
, connect = require('connect')
, sanitizer = require('validator').sanitize
, daemon = require('daemon');
var program = require('commander')
, http = require('http')
, fs = require('fs')
, socketio = require('socket.io')
, spawn = require('child_process').spawn
, connect = require('connect')
, cookieParser = require('cookie')
, sanitizer = require('validator').sanitize
, daemon = require('daemon');
/**
* Parse arg
@ -15,11 +16,13 @@ program
.usage('[options] [file ...]')
.option('-p, --port <port>', 'server port, default 9001', Number, 9001)
.option('-n, --number <number>', 'starting lines number, default 10', Number, 10)
.option('-l, --lines <number>', 'number on lines stored in browser, default 2000', Number, 2000)
.option('-l, --lines <lines>', 'number on lines stored in browser, default 2000', Number, 2000)
.option('-d, --daemonize', 'run as daemon')
.option('--pid-path <path>', 'if run as deamon file that will store the process ID, default /var/run/frontail.pid',
.option('-U, --user <username>', 'Basic Auth user', String, false)
.option('-P, --password <password>', 'Basic Auth password', String, false)
.option('--pid-path <path>', 'if run as daemon file that will store the process id, default /var/run/frontail.pid',
String, '/var/run/frontail.pid')
.option('--log-path <path>', 'if run as deamon file that will be used as a log, default /dev/null',
.option('--log-path <path>', 'if run as daemon file that will be used as a log, default /dev/null',
String, '/dev/null')
.parse(process.argv);
@ -31,13 +34,31 @@ if (program.args.length === 0) {
process.exit();
} else {
var files = program.args;
var doAuthorization = false;
if (program.user && program.password) {
doAuthorization = true;
var sessionSecret = String(+new Date()) + Math.random();
var sessionKey = 'sid';
}
}
if (program.daemonize) {
/**
* Daemonize process
*/
var logFile = fs.openSync(program.logPath, 'a');
var args = ['-p', program.port, '-n', program.number, '-l', program.lines];
if (doAuthorization) {
args = args.concat(['-U', program.user, '-P', program.password]);
}
args = args.concat(files);
var proc = daemon.daemon(
__filename,
['-p', program.port, '-n', program.number, files],
args,
{
stdout: logFile,
stderr: logFile
@ -46,23 +67,35 @@ if (program.daemonize) {
fs.writeFileSync(program.pidPath, proc.pid);
} else {
/**
* Server setup
* HTTP server setup
*/
var app = connect()
.use(connect.static(__dirname + '/assets'))
.use(function (req, res) {
fs.readFile(__dirname + '/index.html', function (err, data) {
if (err) {
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end('Interal error');
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data.toString('utf-8').replace(
/__TITLE__/g, 'tail -F ' + files.join(' ')), 'utf-8'
);
}
});
});
var app = connect();
if (doAuthorization) {
app
.use(connect.cookieParser())
.use(connect.session({secret: sessionSecret, key: sessionKey}))
.use(connect.basicAuth(function (user, password) {
return program.user == user & program.password == password;
}));
}
app
.use(connect.static(__dirname + '/web/assets'))
.use(function (req, res) {
fs.readFile(__dirname + '/web/index.html', function (err, data) {
if (err) {
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end('Internal error');
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data.toString('utf-8').replace(
/__TITLE__/g, 'tail -F ' + files.join(' ')), 'utf-8'
);
}
});
});
var server = http.createServer(app).listen(program.port);
/**
@ -70,6 +103,21 @@ if (program.daemonize) {
*/
var io = socketio.listen(server, {log: false});
if (doAuthorization) {
io.set('authorization', function(handshakeData, accept) {
if (handshakeData.headers.cookie) {
var cookie = cookieParser.parse(handshakeData.headers.cookie);
var sessionId = connect.utils.parseSignedCookie(cookie[sessionKey], sessionSecret);
if (sessionId) {
return accept(null, true);
}
return accept('Invalid cookie', false);
} else {
return accept('No cookie in header', false);
}
});
}
/**
* When connected send starting data
*/

View File

@ -1,6 +1,6 @@
{
"name": "frontail",
"version": "0.3.1",
"version": "0.3.2",
"description": "tail -F output in browser",
"homepage": "https://github.com/mthenw/frontail",
"author": {
@ -16,7 +16,8 @@
"socket.io": "0.9.13",
"connect": "2.7.3",
"validator": "0.4.24",
"daemon": "1.0.0"
"daemon": "1.0.0",
"cookie": "0.1.0"
},
"repository": {
"type": "git",