forked from hardillb/node-red-alexa-home-skill-web
-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
101 changed files
with
8,120 additions
and
2,706 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
FROM node:8 | ||
FROM node:12.10 | ||
|
||
ENV NODE_ENV production | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Depends | ||
/////////////////////////////////////////////////////////////////////////// | ||
var favicon = require('serve-favicon') | ||
var flash = require('connect-flash'); | ||
var morgan = require('morgan'); | ||
var express = require('express'); | ||
const session = require('express-session'); | ||
const mongoStore = require('connect-mongo')(session); | ||
var passport = require('passport'); | ||
var bodyParser = require('body-parser'); | ||
//var cookieParser = require('cookie-parser'); | ||
/////////////////////////////////////////////////////////////////////////// | ||
// MongoDB | ||
/////////////////////////////////////////////////////////////////////////// | ||
var db = require('./config/db'); | ||
// Schema ======================= | ||
var Account = require('./models/account'); | ||
var Topics = require('./models/topics'); | ||
var passport = require('passport'); | ||
var BasicStrategy = require('passport-http').BasicStrategy; | ||
var LocalStrategy = require('passport-local').Strategy; | ||
var logger = require('./config/logger'); | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Variables | ||
/////////////////////////////////////////////////////////////////////////// | ||
var debug = (process.env.ALEXA_DEBUG || false); | ||
// MongoDB Settings, used for expression session handler DB connection | ||
var mongo_user = (process.env.MONGO_USER); | ||
var mongo_password = (process.env.MONGO_PASSWORD); | ||
var mongo_host = (process.env.MONGO_HOST || "mongodb"); | ||
var mongo_port = (process.env.MONGO_PORT || "27017"); | ||
// MQTT Settings | ||
var mqtt_user = (process.env.MQTT_USER); | ||
var mqtt_password = (process.env.MQTT_PASSWORD); | ||
var mqtt_port = (process.env.MQTT_PORT || "1883"); | ||
var mqtt_url = (process.env.MQTT_URL || "mqtt://mosquitto:" + mqtt_port); | ||
// Cookie Secret | ||
var cookieSecret = (process.env.COOKIE_SECRET || 'ihytsrf334'); | ||
if (cookieSecret == 'ihytsrf334') {logger.log("warn", "[App] Using default Cookie Secret, please supply new secret using COOKIE_SECRET environment variable")} | ||
else {logger.log("info", "[App] Using user-defined cookie secret")} | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Passport Configuration | ||
/////////////////////////////////////////////////////////////////////////// | ||
passport.use(new LocalStrategy(Account.authenticate())); | ||
passport.use(new BasicStrategy(Account.authenticate())); | ||
passport.serializeUser(Account.serializeUser()); | ||
passport.deserializeUser(Account.deserializeUser()); | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Main | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Check admin account exists, if not create it using same credentials as MQTT user/password supplied | ||
Account.findOne({username: mqtt_user}, function(error, account){ | ||
if (!error && !account) { | ||
Account.register(new Account({username: mqtt_user, email: '', mqttPass: '', superuser: 1}), | ||
mqtt_password, function(err, account){ | ||
var topics = new Topics({topics: [ | ||
'command/' +account.username+'/#', | ||
'state/' + account.username + '/#', | ||
'response/' + account.username + '/#', | ||
'message/' + account.username + '/#' | ||
]}); | ||
topics.save(function(err){ | ||
if (!err){ | ||
var s = Buffer.from(account.salt, 'hex').toString('base64'); | ||
var h = Buffer.from(account.hash, 'hex').toString(('base64')); | ||
var mqttPass = "PBKDF2$sha256$901$" + account.salt + "$" + account.hash; | ||
Account.updateOne( | ||
{username: account.username}, | ||
{$set: {mqttPass: mqttPass, topics: topics._id}}, | ||
function(err, count){ | ||
if (err) { | ||
logger.log('error', err); | ||
} | ||
} | ||
); | ||
} | ||
}); | ||
}); | ||
} else { | ||
logger.log('info', "[App] Superuser MQTT account, " + mqtt_user + " already exists"); | ||
} | ||
}); | ||
|
||
var app = express(); | ||
app.set('view engine', 'ejs'); | ||
app.enable('trust proxy'); | ||
app.use(favicon('static/favicon.ico')); | ||
app.use(morgan("combined", {stream: logger.stream})); // change to use Winston | ||
//app.use(cookieParser(cookieSecret)); | ||
app.use(flash()); | ||
// Session handler | ||
app.use(session({ | ||
store: new mongoStore({ | ||
url: "mongodb://" + mongo_user +":" + mongo_password + "@" + mongo_host + ":" + mongo_port + "/sessions" | ||
}), | ||
resave: true, | ||
saveUninitialized: false, | ||
secret: cookieSecret, | ||
cookie: { | ||
secure: true | ||
} | ||
})); | ||
app.use(bodyParser.json()); | ||
app.use(bodyParser.urlencoded({ extended: false })); | ||
app.use(passport.initialize()); | ||
app.use(passport.session()); | ||
|
||
function requireHTTPS(req, res, next) { | ||
if (req.get('X-Forwarded-Proto') === 'http') { | ||
var url = 'https://' + req.get('host'); | ||
if (req.get('host') === 'localhost') { | ||
url += ':' + port; | ||
} | ||
url += req.url; | ||
return res.redirect(url); | ||
} | ||
next(); | ||
} | ||
|
||
app.use(requireHTTPS); | ||
|
||
app.use('/',express.static('static')); // Static content router | ||
app.use('/octicons', express.static('node_modules/@primer/octicons/build'), express.static('node_modules/@primer/octicons/build/svg')); // Octicons router | ||
|
||
/////////////////////////////////////////////////////////////////////////// | ||
// Load Routes | ||
/////////////////////////////////////////////////////////////////////////// | ||
const rtDefault = require('./routes/default'); | ||
const rtAdmin = require('./routes/admin'); | ||
const rtAuth = require('./routes/auth'); | ||
const rtGhome = require('./routes/ghome'); | ||
const rtAlexa = require('./routes/alexa'); | ||
app.use('/', rtDefault); | ||
app.use('/admin', rtAdmin); // Admin Interface | ||
app.use('/auth', rtAuth); // OAuth endpoints | ||
app.use('/api/ghome', rtGhome); // Google Home API | ||
app.use('/api/v1', rtAlexa); // Alexa API | ||
|
||
var state = require('./state'); // Load State API | ||
|
||
module.exports = app; | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Depends | ||
/////////////////////////////////////////////////////////////////////////// | ||
var mongoose = require('mongoose'); | ||
var logger = require('./logger'); // Moved to own module | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Variables | ||
/////////////////////////////////////////////////////////////////////////// | ||
// MongoDB Settings | ||
var mongo_user = (process.env.MONGO_USER); | ||
var mongo_password = (process.env.MONGO_PASSWORD); | ||
var mongo_host = (process.env.MONGO_HOST || "mongodb"); | ||
var mongo_port = (process.env.MONGO_PORT || "27017"); | ||
mongo_url = "mongodb://" + mongo_user +":" + mongo_password + "@" + mongo_host + ":" + mongo_port + "/users"; | ||
mongoose.Promise = global.Promise; | ||
var mongoose_connection = mongoose.connection; | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Connect to Mongo Instance | ||
/////////////////////////////////////////////////////////////////////////// | ||
mongoose_connection.on('connecting', function() { | ||
logger.log('info', "[Core] Connecting to MongoDB..."); | ||
}); | ||
mongoose_connection.on('error', function(error) { | ||
logger.log('error', "[Core] MongoDB connection: " + error); | ||
//mongoose.disconnect(); | ||
}); | ||
mongoose_connection.on('connected', function() { | ||
logger.log('info', "[Core] MongoDB connected!"); | ||
}); | ||
mongoose_connection.once('open', function() { | ||
logger.log('info', "[Core] MongoDB connection opened!"); | ||
}); | ||
mongoose_connection.on('reconnected', function () { | ||
logger.log('info', "[Core] MongoDB reconnected!"); | ||
}); | ||
mongoose_connection.on('disconnected', function() { | ||
logger.log('warn', "[Core] MongoDB disconnected!"); | ||
}); | ||
|
||
// Fix Mongoose Deprecation Warnings; https://mongoosejs.com/docs/deprecations.html | ||
mongoose.set('useNewUrlParser', true); | ||
mongoose.set('useCreateIndex', true); | ||
mongoose.set('useFindAndModify', false); | ||
mongoose.set('useUnifiedTopology', true); | ||
|
||
logger.log('info', "[Core] Connecting to MongoDB server: mongodb://" + mongo_host + ":" + mongo_port + "/users"); | ||
mongoose.connect(mongo_url, { | ||
useNewUrlParser: true, | ||
useUnifiedTopology: true, | ||
autoReconnect: true, | ||
reconnectTries: Number.MAX_VALUE, | ||
reconnectInterval: 1000 | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Depends | ||
/////////////////////////////////////////////////////////////////////////// | ||
const { format, createLogger, transports } = require('winston'); | ||
const fs = require('fs'); | ||
const crypto = require('crypto'); | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Variables | ||
/////////////////////////////////////////////////////////////////////////// | ||
var debug = (process.env.ALEXA_DEBUG || false); | ||
var awscredentials = '/root/.aws/credentials' | ||
var logGroup = (process.env.WEB_HOSTNAME || "node-red") | ||
var startTime = new Date().toISOString(); | ||
var consoleLoglevel = "info"; | ||
if (debug == "true") {consoleLoglevel = "debug"}; | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Exports | ||
/////////////////////////////////////////////////////////////////////////// | ||
const logger = createLogger({ | ||
transports: [ | ||
// Console Transport | ||
new transports.Console({ | ||
level: consoleLoglevel, | ||
format: format.combine( | ||
format.timestamp(), | ||
format.colorize(), | ||
format.simple() | ||
), | ||
handleExceptions: true | ||
}) | ||
] | ||
}); | ||
// Create logger stream object for use with morgan | ||
logger.stream = { | ||
write: function(message, encoding) { | ||
// use the 'verbose' log level | ||
logger.verbose(message); | ||
}, | ||
}; | ||
|
||
// Check for AWS credentials | ||
fs.access(awscredentials, fs.F_OK, (err) => { | ||
if (err) { | ||
logger.log('warn', '[Logger] AWS credentials file does not exist at ~/.aws/credentials. Cludwatch logging disabled.'); | ||
return | ||
} | ||
// Setup AWS CloudWatch Transport | ||
const WinstonCloudwatch = require('winston-cloudwatch'); | ||
logger.add(new WinstonCloudwatch({ | ||
logGroupName: logGroup, | ||
logStreamName: function() { | ||
// Spread log streams across dates as the server stays up | ||
let date = new Date().toISOString().split('T')[0]; | ||
return 'express-server-' + date + '-' + | ||
crypto.createHash('md5') | ||
.update(startTime) | ||
.digest('hex'); | ||
}, | ||
awsRegion: 'eu-west-1', | ||
jsonMessage: true | ||
})); | ||
}) | ||
|
||
module.exports = logger; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Depends | ||
/////////////////////////////////////////////////////////////////////////// | ||
var logger = require('./logger'); // Moved to own module | ||
/////////////////////////////////////////////////////////////////////////// | ||
// Redis Client Config | ||
/////////////////////////////////////////////////////////////////////////// | ||
var client = require('redis').createClient({ | ||
host: 'redis', | ||
retry_strategy: function (options) { | ||
if (options.error && options.error.code === 'ECONNREFUSED') { | ||
return new Error('The server refused the connection'); | ||
} | ||
if (options.total_retry_time > 1000 * 60 * 60) { | ||
//logger.log('error', "[REDIS] Retry time exhausted"); | ||
return new Error('Retry time exhausted'); | ||
} | ||
if (options.attempt > 100) { | ||
// End reconnecting with built in error | ||
logger.log('error', "[Core] Redis server connection retry limit exhausted"); | ||
return undefined; | ||
} | ||
// reconnect after | ||
//logger.log('error', "[REDIS] Attempting reconnection after set interval"); | ||
return Math.min(options.attempt * 1000, 10000); | ||
} | ||
}); | ||
client.on('connect', function() { | ||
logger.log('info', "[Core] Connecting to Redis server..."); | ||
}); | ||
client.on('ready', function() { | ||
logger.log('info', "[Core] Redis connection ready!"); | ||
}); | ||
client.on('reconnecting', function() { | ||
logger.log('info', "[Core] Attempting to reconnect to Redis server"); | ||
}); | ||
client.on('error', function (err) { | ||
logger.log('error', "[Core] Unable to connect to Redis server"); | ||
}); | ||
|
||
module.exports = client; |
Oops, something went wrong.