Cleaned up file layout
This commit is contained in:
@@ -19,6 +19,15 @@ const middleware = require('./middleware/auth');
|
|||||||
// Grab the projects PubSub
|
// Grab the projects PubSub
|
||||||
app.contoller = require('./controller');
|
app.contoller = require('./controller');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start background services
|
||||||
|
* These services run independently of the HTTP server:
|
||||||
|
* - host_lookup: Unix socket server for OpenResty host lookups
|
||||||
|
* - host_scheduler: Scheduled tasks for wildcard cert renewal
|
||||||
|
*/
|
||||||
|
require('./services/host_lookup');
|
||||||
|
require('./services/host_scheduler');
|
||||||
|
|
||||||
// Push pubsub over the socket and back.
|
// Push pubsub over the socket and back.
|
||||||
app.onListen.push(function(){
|
app.onListen.push(function(){
|
||||||
app.io.use(middleware.authIO);
|
app.io.use(middleware.authIO);
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const Table = require('../models');
|
|
||||||
const {User, AuthToken} = Table.models;
|
|
||||||
|
|
||||||
|
|
||||||
class Auth{
|
|
||||||
static errors = {
|
|
||||||
login: function(){
|
|
||||||
let error = new Error('LoginFailed');
|
|
||||||
error.name = 'LoginFailed';
|
|
||||||
error.message = `Invalid Credentials, login failed.`;
|
|
||||||
error.status = 401;
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async login(data){
|
|
||||||
try{
|
|
||||||
let user = await User.login(data);
|
|
||||||
let token = await AuthToken.create({username: user.username});
|
|
||||||
|
|
||||||
return {user, token}
|
|
||||||
}catch(error){
|
|
||||||
console.log('login error', error);
|
|
||||||
throw this.errors.login();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async checkToken(token){
|
|
||||||
try{
|
|
||||||
token = await AuthToken.get(token);
|
|
||||||
if(token && token.check()) return token;
|
|
||||||
|
|
||||||
throw this.errors.login();
|
|
||||||
}catch(error){
|
|
||||||
console.log('check error', error);
|
|
||||||
throw this.errors.login();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async logout(data){
|
|
||||||
let token = await AuthToken.get(data);
|
|
||||||
await token.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {Auth};
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const {Host} = require('../models/host');
|
|
||||||
const {SocketServerJson} = require('../models/socket_server_json');
|
|
||||||
const conf = require('../conf');
|
|
||||||
|
|
||||||
|
|
||||||
const socket = new SocketServerJson({
|
|
||||||
socketFile: conf.socketFile,
|
|
||||||
onData: function(data, clientSocket) {
|
|
||||||
try{
|
|
||||||
console.log('socket lookup', data)
|
|
||||||
let parentHost = Host.lookUp(data['domain']);
|
|
||||||
console.log('socket found host', parentHost);
|
|
||||||
if(!parentHost) return clientSocket.write(JSON.stringify({}));
|
|
||||||
if(!parentHost.wildcard_parent){
|
|
||||||
parentHost.wildcard_parent = parentHost.host;
|
|
||||||
Host.addCache(data['domain'], parentHost);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const [key, value] of Object.entries(parentHost)) {
|
|
||||||
parentHost[key] = String(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
clientSocket.write(JSON.stringify(parentHost));
|
|
||||||
}catch(error){
|
|
||||||
console.error('controler/hosts onData error', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onListen: function(){
|
|
||||||
console.log('Unix socket listening on', conf.socketFile)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
auth: require('./auth'),
|
|
||||||
ps: require('./pubsub'),
|
ps: require('./pubsub'),
|
||||||
host: require('./host'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {Auth} = require('../controller/auth');
|
const {Auth} = require('../models/auth');
|
||||||
|
|
||||||
async function auth(req, res, next){
|
async function auth(req, res, next){
|
||||||
try{
|
try{
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const net = require('net');
|
|
||||||
const fs = require('fs');
|
|
||||||
const {CallbackQueue} = require('../utils/callback_queue')
|
|
||||||
|
|
||||||
class SocketServerJson {
|
|
||||||
constructor(args){
|
|
||||||
this.socketFile = args.socketFile;
|
|
||||||
this.onData = new CallbackQueue(args.onData, this);
|
|
||||||
this.onListen = new CallbackQueue(args.onListen, this);
|
|
||||||
this.onError = new CallbackQueue(args.onError);
|
|
||||||
this.onCLientNew = new CallbackQueue(args.onCLientNew);
|
|
||||||
this.onCLientClose = new CallbackQueue(args.onCLientClose);
|
|
||||||
this.onCLientError = new CallbackQueue(args.onCLientClose);
|
|
||||||
|
|
||||||
this.onListen.push(function(){
|
|
||||||
fs.chmodSync(args.socketFile, '777');
|
|
||||||
})
|
|
||||||
|
|
||||||
this.listen();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
__resetSocketFile(callback){
|
|
||||||
let instance = this;
|
|
||||||
|
|
||||||
fs.stat(this.socketFile, function (err, stats) {
|
|
||||||
if (stats) {
|
|
||||||
fs.unlink(instance.socketFile, function(err){
|
|
||||||
if(err){
|
|
||||||
// This should never happen.
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
callback(...arguments)
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__setUpServer(){
|
|
||||||
|
|
||||||
let instance = this;
|
|
||||||
this.socket = net.createServer();
|
|
||||||
|
|
||||||
this.socket.on('connection', function(clientSocket){
|
|
||||||
let buffer = '';
|
|
||||||
|
|
||||||
clientSocket.on('data', function(data){
|
|
||||||
buffer += data.toString();
|
|
||||||
try{
|
|
||||||
instance.onData.call(JSON.parse(data), clientSocket)
|
|
||||||
buffer = ''
|
|
||||||
// clientSocket.write(JSON.stringify(Host.lookUp(buffer)|| {host: 'none'}));
|
|
||||||
|
|
||||||
}catch(error){
|
|
||||||
;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
clientSocket.on('close', instance.onCLientClose.call.bind(instance.onCLientClose));
|
|
||||||
|
|
||||||
clientSocket.on('error', instance.onCLientError.call.bind(instance.onCLientError));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
this.socket.on('error', this.onError.call.bind(this.onError))
|
|
||||||
|
|
||||||
this.socket.on('listening', this.onListen.call.bind(this.onListen));
|
|
||||||
}
|
|
||||||
|
|
||||||
listen(){
|
|
||||||
let instance = this;
|
|
||||||
|
|
||||||
this.__setUpServer();
|
|
||||||
|
|
||||||
this.__resetSocketFile(function(){
|
|
||||||
instance.socket.listen(instance.socketFile);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {SocketServerJson};
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
const { Auth } = require('../controller/auth');
|
const { Auth } = require('../models/auth');
|
||||||
|
|
||||||
|
|
||||||
router.post('/login', async function(req, res, next){
|
router.post('/login', async function(req, res, next){
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {Host} = require('../models/host');
|
||||||
|
const {SocketServerJson} = require('../utils/unix_socket_json');
|
||||||
|
const conf = require('../conf');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host Lookup Service
|
||||||
|
*
|
||||||
|
* Unix socket server that handles host/domain lookup requests from OpenResty.
|
||||||
|
* This provides the bridge between nginx (Lua) and the Node.js host management system.
|
||||||
|
*
|
||||||
|
* Flow:
|
||||||
|
* 1. OpenResty sends domain lookup request via Unix socket
|
||||||
|
* 2. Service queries Host model (supports wildcards via lookup tree)
|
||||||
|
* 3. Returns host configuration (IP, port, SSL settings, etc.)
|
||||||
|
* 4. All values converted to strings for Redis compatibility
|
||||||
|
*
|
||||||
|
* Redis Compatibility:
|
||||||
|
* All object values are converted to strings before sending because:
|
||||||
|
* - Redis stores everything as strings
|
||||||
|
* - OpenResty's primary lookup path uses Redis directly (hgetall)
|
||||||
|
* - This socket is a fallback when Redis cache misses
|
||||||
|
* - Both paths must return identical data structures to Lua consumer
|
||||||
|
*/
|
||||||
|
|
||||||
|
const socket = new SocketServerJson({
|
||||||
|
socketFile: conf.socketFile,
|
||||||
|
|
||||||
|
onData: function(data, clientSocket) {
|
||||||
|
try{
|
||||||
|
// Try to match the requested host name using the lookup tree
|
||||||
|
let parentHost = Host.lookUp(data['domain']);
|
||||||
|
|
||||||
|
// If we don't have a match, return empty object
|
||||||
|
if(!parentHost) return clientSocket.write(JSON.stringify({}));
|
||||||
|
|
||||||
|
// If the matched host belongs to a wildcard domain, set wildcard_parent
|
||||||
|
// This allows child domains to use the parent's wildcard SSL certificate
|
||||||
|
if(!parentHost.wildcard_parent){
|
||||||
|
parentHost.wildcard_parent = parentHost.host;
|
||||||
|
Host.addCache(data['domain'], parentHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert all values to strings for Redis compatibility
|
||||||
|
// OpenResty expects the same data format from both Redis and this socket
|
||||||
|
for(const [key, value] of Object.entries(parentHost)) {
|
||||||
|
parentHost[key] = String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSocket.write(JSON.stringify(parentHost));
|
||||||
|
}catch(error){
|
||||||
|
console.error('services/host_lookup onData error', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onListen: function(){
|
||||||
|
console.log('Host lookup service listening on', conf.socketFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {socket};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {Host} = require('../models/host');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host Scheduler Service
|
||||||
|
*
|
||||||
|
* Manages scheduled tasks for host-related operations:
|
||||||
|
* - Wildcard SSL certificate renewal checks
|
||||||
|
*
|
||||||
|
* Schedule:
|
||||||
|
* - Initial check: 30 seconds after application starts
|
||||||
|
* - Recurring checks: Every 24 hours (86400000ms)
|
||||||
|
*
|
||||||
|
* The checkWildcardForRenew method:
|
||||||
|
* - Iterates through all hosts in the system
|
||||||
|
* - Checks if wildcard certificates are expiring within 30 days
|
||||||
|
* - Automatically renews certificates that are approaching expiration
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Initial wildcard cert check 30 seconds after app starts
|
||||||
|
// Delay allows the system to fully initialize before checking certs
|
||||||
|
setTimeout(Host.checkWildcardForRenew, 30000);
|
||||||
|
|
||||||
|
// Check wildcard certs once every 24 hours
|
||||||
|
// Ensures certificates are renewed well before expiration
|
||||||
|
setInterval(Host.checkWildcardForRenew, 86400000);
|
||||||
|
|
||||||
|
console.log('Host scheduler service initialized');
|
||||||
|
console.log('- Wildcard cert check: 30s after start, then every 24h');
|
||||||
|
|
||||||
|
module.exports = {};
|
||||||
Reference in New Issue
Block a user