fst – Rev 1
?pathlinks?
#!/usr/bin/env node
const MetricsData = require('./MetricsData.js')
const SyncData = require('./SyncData.js')
const symmetric = require('./symmetric.js')
const fs = require('fs')
const path = require('path')
const YAML = require('yamljs')
const { createLogger, format, transports } = require('winston')
const net = require('net')
const express = require('express')
const whois = require('whois')
const marked = require('marked')
const passport = require('passport')
const Strategy = require('passport-local').Strategy
// Set options for marked.js
marked.setOptions({
renderer: new marked.Renderer(),
highlight: function (code) {
return require('highlight.js').highlightAuto(code).value
},
pedantic: false,
gfm: true,
tables: true,
breaks: true,
sanitize: false,
smartLists: true,
smartypants: false,
xhtml: false
})
// Load configuration file.
const config = YAML.load(
path.join(
path.dirname(
require.main.filename
),
'config.yml'
)
)
// Set up logger.
const logger = createLogger({
format: format.combine(
format.splat(),
format.simple()
),
transports: [
new transports.Console(),
new transports.File({ filename: config.log })
]
})
// Initialize the metrics object.
var metrics
try {
const store = fs.readFileSync(config.metrics.store)
metrics = MetricsData.fromJSON(store)
logger.log('info', 'metrics store has been loaded %s', config.metrics.store)
} catch (error) {
logger.info('store file not found, starting fresh')
metrics = new MetricsData()
}
// Create socket server to listen for payloads.
var server = net.createServer({ host: config.metrics.host, port: config.metrics.port }, function (stream) {
stream.on('data', processPayload)
}).on('listening', function () {
logger.info('metrics server running, waiting for payloads')
}).on('error', function (error) {
logger.log('error', 'metrics server could not listen on configured host %s and port %s',
config.metrics.host,
config.metrics.port
)
})
// Listen on the configured socket.
server.listen(config.metrics.port, config.metrics.host)
// Initialize passport authentication.
passport.use(new Strategy(passportStrategy))
passport.serializeUser(passportSerializeUser)
passport.deserializeUser(passportDeserializeUser)
// Set up web server.
const app = express()
// Configure view engine to render EJS templates.
app.set('views', config.metrics.wwwroot)
app.set('view engine', 'ejs')
// Static files
app.use(express.static(config.metrics.wwwroot))
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('cookie-parser')())
app.use(require('body-parser').urlencoded({ extended: true }))
app.use(require('express-session')({ secret: 'shazam', resave: false, saveUninitialized: false }))
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize())
app.use(passport.session())
app.listen(config.metrics.wwwport, () => {
logger.log('info', 'web interface listening on port %s', config.metrics.wwwport)
})
// Login, logout and user processing.
app.get('/',
(req, res) => {
res.render('login', { user: req.user })
})
app.get('/login',
(req, res) => {
res.render('login')
})
app.post('/login',
passport.authenticate('local', { failureRedirect: '/unauthorized' }),
(req, res) => {
res.render('index')
})
app.get('/logout',
(req, res) => {
req.logout()
res.redirect('/')
})
app.get('/unauthorized',
(req, res) => {
res.render('unauthorized')
})
// All views.
// All EJS: fs.readdirSync(config.metrics.wwwroot).filter((view) => /\.ejs$/.test(view)).map((view) => `/${view.replace(/\.ejs$/gm, '')}`)
app.get('/index',
require('connect-ensure-login').ensureLoggedIn(),
(req, res) => {
const view = req.originalUrl.replace(/^\//gm, '')
res.render(view, { user: req.user, view: view })
})
// Send metrics.
app.get('/metrics',
require('connect-ensure-login').ensureLoggedIn(),
(req, res) =>
res.send(JSON.stringify(metrics)))
// Process whois requests.
app.get('/whois/:host',
require('connect-ensure-login').ensureLoggedIn(),
(req, res) => {
whois.lookup(req.params.host, (err, data) => {
if (err) {
res.send('Failed to retireve WHOIS information. Please try again later...')
return
}
res.send(marked(data))
})
})
// Retrieve a list of peers.
app.get('/peers',
require('connect-ensure-login').ensureLoggedIn(),
(req, res) => {
res.send(JSON.stringify(metrics.peers))
})
function passportSerializeUser(user, cb) {
cb(null, user.id)
}
function passportDeserializeUser(id, cb) {
var user = config.metrics.users.filter((user) => {
return user.id === id
}).shift()
if (typeof user === 'undefined' || user === null)
return cb(err)
return cb(null, user)
}
function passportStrategy(username, password, cb) {
var user = config.metrics.users.filter((user) => {
return user.username === username && user.password === password
}).shift()
if (typeof user === 'undefined' || user === null)
return cb(null, false)
return cb(null, user)
}
function processPayload(message) {
// Decrypt the payload.
var decrypted = ""
try {
decrypted = symmetric.decrypt(message, config.secret)
}
catch (error) {
logger.log('warn', 'decrypting payload %s failed with error %s', message, error)
return
}
// Deserialize the payload.
var syncMessage
try {
syncMessage = SyncData.fromJSON(decrypted)
} catch (error) {
// Not a sync message so ignore it.
return
}
metrics.update(syncMessage)
var json = JSON.stringify(metrics)
logger.log('info', 'metrics updated %s', json)
fs.writeFile(config.metrics.store, json, function (error) {
if (error) {
logger.log('error', 'could not write metrics file %s', config.metrics.store)
}
})
}
Generated by GNU Enscript 1.6.5.90.