Added socket.io

This commit is contained in:
2024-07-31 19:01:55 -04:00
parent fc66225cf5
commit 441e372987
23 changed files with 551 additions and 151 deletions
+26 -35
View File
@@ -7,27 +7,36 @@ const express = require('express');
// Set up the express app.
const app = express();
// Hold list of functions to run when the server is ready
app.onListen = [];
// Allow the express app to be exported into other files.
module.exports = app;
// Build the conf object from the conf files.
app.conf = require('./conf/conf');
// List of front end node modules to be served
const frontEndModules = ['bootstrap', 'mustache', 'jquery', 'jquery-ui','@fortawesome',
'moment',
];
// Server front end modules
// https://stackoverflow.com/a/55700773/3140931
frontEndModules.forEach(dep => {
app.use(`/static-modules/${dep}`, express.static(path.join(__dirname, `node_modules/${dep}`)))
});
// Hold onto the auth middleware
const middleware = require('./middleware/auth');
// Grab the projects PubSub
app.contoller = require('./controller');
// Push pubsub over the socket and back.
app.onListen.push(function(){
app.io.use(middleware.authIO);
app.contoller.ps.subscribe(/./g, function(data, topic){
app.io.emit('P2PSub', { topic, data });
});
app.io.on('connection', (socket) => {
// console.log('socket', socket)
var user = socket.user;
socket.on('P2PSub', (msg) => {
app.contoller.ps.publish(msg.topic, {...msg.data, __from:socket.user});
// socket.broadcast.emit('P2PSub', msg);
});
});
});
// load the JSON parser middleware. Express will parse JSON into native objects
// for any request that has JSON in its content type.
app.use(express.json());
@@ -36,29 +45,11 @@ app.use(express.json());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// Have express server static content( images, CSS, browser JS) from the public
// local folder.
app.use('/static', express.static(path.join(__dirname, 'public')))
// Routes for front end content.
app.use('/', require('./routes/render'));
// API routes for authentication.
app.use('/api/auth', require('./routes/auth'));
// API routes for working with users. All endpoints need to be have valid user.
app.use('/api/user', middleware.auth, require('./routes/user'));
// API routes for working with hosts. All endpoints need to be have valid user.
app.use('/api/host', middleware.auth, require('./routes/host'));
// API routes for working with hosts. All endpoints need to be have valid user.
app.use('/api/cert', middleware.auth, require('./routes/cert'));
app.controler = {
host: require('./controler/host')
}
// Routes for API
app.use('/api', require('./routes/api'));
// Catch 404 and forward to error handler. If none of the above routes are
// used, this is what will be called.
+11 -3
View File
@@ -7,12 +7,13 @@
var app = require('../app');
var debug = require('debug')('proxy-api:server');
var http = require('http');
const conf = require('../conf');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.NODE_PORT || '3000');
var port = normalizePort(process.env.NODE_PORT || conf.port || '3000');
app.set('port', port);
/**
@@ -21,6 +22,9 @@ app.set('port', port);
var server = http.createServer(app);
var io = require('socket.io')(server);
app.io = io;
/**
* Listen on provided port, on all network interfaces.
*/
@@ -86,5 +90,9 @@ function onListening() {
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
console.log('Listening on ' + bind);
for(let listener of app.onListen){
listener()
}
}
+56
View File
@@ -0,0 +1,56 @@
'use strict';
const {User} = require('../models/user');
const {AuthToken} = require('../models/token');
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){
throw this.errors.login();
}
}
static async logout(data){
let token = await AuthToken.get(data);
await token.destroy();
}
}
Auth.logOut = async function(data){
try{
}catch(error){
throw error;
}
}
module.exports = {Auth};
@@ -2,7 +2,7 @@
const {Host} = require('../models/host');
const {SocketServerJson} = require('../models/socket_server_json');
const conf = require('../app').conf;
const conf = require('../conf');
const socket = new SocketServerJson({
+8
View File
@@ -0,0 +1,8 @@
'use strict';
module.exports = {
auth: require('./auth'),
ps: require('./pubsub'),
host: require('./host'),
}
+5
View File
@@ -0,0 +1,5 @@
const {PubSub} = require('p2psub');
ps = new PubSub();
module.exports = ps;
+28
View File
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAykMghkRxBOfK
niTICXpW3CahhIHf/uCDF1ENMf1uTfaextHtIn/SVvpQ+CcOWmNNb34aW/VYNGa9
P/AidMTRVPRWUuyEjsRSS8lhH6xRmnEeX6dnIfY7XfJQ3HEoIY7yoRgu2udltCgq
qSedyQ5l3F6h9r4gxWyNXcZuYeyXR2YAyRwKIsH7I58I0rgq/sw4Lgb+wFiQHXu/
ocfnTcAqhikiFJcgZUkIO3HmrTeKjT2T1LrZZ84uWEZ5NHnN4TmpaTAsLrhiNU8d
LXkPR61Y8tr7IGouvsoKj6PQHtm6bqjRp1iKQJ9aTUcFn7EEf/hFijHLPC1nIA+S
czY/BiR9AgMBAAECggEAK/fVEF1ezZHLVUv04oQ62QVzcAG65v2HcY5HR2WfwWDZ
foOki9sC4NNCWmYF7kGSBS6IyXUwgrHMvpuO5iTQYFdqNCfMVj0DLCupnVNuZtv8
sWsqUByQPiDiayujSP5CTjaMP99fx7OrN3OFm/gnJvb3xCN0YB/2blU1NKZzoVpa
nCJDfa632Aci2pMbyOSx++HeH89dCY+ruWFn36Bz9MJ1jgOZ1dBKxfUogPHI/O2u
9tFLsLHxSfyPIjLfLrwZ0NGpmiRROUQeVQJBKhEaQPfIa7axq3fz6yPZZ+H6ExKp
LATKuLDTo8MzcSYTlL8UAvCU+P9chklM8ZYmtQCypwKBgQD7mTaFLkjH9u2A0TPt
HUn5yjpg0TMCXj06AISoPg+NGBB8UIyuZME2tbkT2J4sPMAergHb9sMmae2paSz3
8w4AZF5HL/A6eaAdzYtGc2YT+mTAV9zBJ0HzoNY/YPBdBXqRQwsmqph5NZOv3NzQ
QoNeDij7HJBR/fIqvoZ7JMxs1wKBgQDEKazRfO8274esgtQzLoPQIg+rhv5Sktda
pA7pbx92WtfPzWi0deT+Ks7rqlpoTdDA7SIAML5UgqyWa9NP/EmyDlZBpoeWOn+9
CYCkNjkzu2dudgcmYD3X9iIIl1+2ibF8jm5QYxX5nkq8cuySUM/2iw5IUpHUwRLG
1Juz91IaywKBgQDjRzprAK6ahMNztIgV0Hl8/mPSBejwYLUqakFrwfRGXtC1nAYZ
m8a2Z15zQSFRkOd0T3g6fiU31ETu3qXSrmudiw1nfTSjfi9X/M+tqp0xuuW8oyI2
EgKP1GD2C9nWDhb0lf3CxiTKic2J9hg6wXruQhhfDySIDMDwQAA3ybwpLQKBgC8+
ekjZ9iMc/Wgm+kR5Z3WxPmTpVkc85nEGIjFGeiVfK6r4pccQvd4ZIUzQ8oU8eJJ+
ijnRg4WHE1oHDhWthXJE0bFuEim0XR+CMmFaTdyPvhF0i7RKaZqhxQCctIiaEQ0W
oKrrslc0MHvCkgeLPwr54q64dDbxaTxJ6FYnsraRAoGAYkxElEMtmF1jh6Mb/txJ
S0ElZdSTFgHQE2VquSxr1yAHac6894jEsY22OrPmSSWlELZ74w/NsZqs1zO8lPTH
jrUj2DAuQUx38SZcrijs9Rz5fhE0dk9ofNXlz8Cvyj6cXnogEy0bx+owqqIqVCpl
aL9umqfjjonJzMQUefQLIqU=
-----END PRIVATE KEY-----
+17 -7
View File
@@ -1,17 +1,27 @@
'use strict';
const {Auth} = require('../models/auth');
const { Auth } = require('../controller/auth');
async function auth(req, res, next){
try{
let user = await Auth.checkToken({token: req.header('auth-token')});
if(user.username){
req.user = user;
return next();
}
req.token = await Auth.checkToken(req.header('auth-token'));
req.user = await req.token.getUser();
return next();
}catch(error){
next(error);
}
}
module.exports = {auth};
async function authIO(socket, next){
try{
let token = await Auth.checkToken(socket.handshake.auth.token || 0);
socket.user = await token.getUser();
console.log('socket is good!')
next();
}catch(error){
console.log('reject for', socket.handshake.auth.token)
next(error);
}
}
module.exports = {auth, authIO};
@@ -1,7 +1,9 @@
'use strict';
const {User} = require('./user');
const {Token, AuthToken} = require('./token');
Auth = {}
let Auth = {}
Auth.errors = {}
Auth.errors.login = function(){
+10 -6
View File
@@ -1,11 +1,12 @@
'use strict';
const Table = require('../utils/redis_model');
const ModelPs = require('../utils/model_pubsub');
const tldExtract = require('tld-extract').parse_host;
const PorkBun = require('../utils/porkbun');
const LetsEncrypt = require('../utils/letsencrypt');
const conf = require('../conf/conf');
const conf = require('../conf');
let porkBun = new PorkBun(conf.porkBun.apiKey, conf.porkBun.secretApiKey);
let letsEncrypt = new LetsEncrypt({
@@ -13,7 +14,6 @@ let letsEncrypt = new LetsEncrypt({
});
class Host extends Table{
static _key = 'host';
static _keyMap = {
@@ -86,7 +86,6 @@ class Host extends Table{
static async add(data, ...args){
try{
let out = await super.add(data, ...args)
await this.buildLookUpObj()
if(out.is_wildcard) await out.createWildcardCert()
@@ -246,8 +245,13 @@ class Host extends Table{
return true;
}
static test(pass){
return `yes ${pass}`
}
}
class Cached extends Table{
static _key = 'host';
static _keyMap = {
@@ -262,7 +266,7 @@ class Cached extends Table{
await Host.buildLookUpObj();
})()
module.exports = {Host};
module.exports = {Host: ModelPs(Host)};
(async function(){
try{
@@ -279,8 +283,8 @@ try{
// })
// console.log('IIFE res:\n', res)
console.log(await Host.listDetail())
// console.log(Host.test(55))
// console.log(await Host.listDetail())
// console.log('IIFE lookup:', Host.lookUp('bld3324sdf.test.holycore.quest'))
+5
View File
@@ -1,6 +1,7 @@
'use strict';
const Table = require('../utils/redis_model');
const {User} = require('./user');
const UUID = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)};
@@ -32,6 +33,10 @@ class AuthToken extends Token{
super(...args);
}
async getUser(){
return await User.get(this.created_by);
}
static async add(data){
data.created_by = data.username;
return super.add(data)
+1 -1
View File
@@ -1,6 +1,6 @@
'use strict';
const conf = require('../app').conf;
const conf = require('../conf');
const User = require(`./user_${conf.userModel}`)
+5 -5
View File
@@ -1,7 +1,7 @@
'use strict';
const Table = require('../utils/redis_model');
const {Token, InviteToken} = require('./token');
// const {Token, InviteToken} = require('./token');
const bcrypt = require('bcrypt');
const saltRounds = 10;
@@ -32,7 +32,7 @@ class User extends Table{
}
}
static async addByInvite(data){
/* static async addByInvite(data){
try{
let token = await InviteToken.get(data.token);
@@ -55,7 +55,7 @@ class User extends Table{
throw error;
}
};
};*/
async setPassword(data){
try{
@@ -67,7 +67,7 @@ class User extends Table{
}
}
async invite(){
/* async invite(){
try{
let token = await InviteToken.add({created_by: this.username});
@@ -76,7 +76,7 @@ class User extends Table{
}catch(error){
throw error;
}
}
}*/
static async login(data){
try{
+223
View File
@@ -24,7 +24,9 @@
"linux-sys-user": "^1.1.8",
"moment": "^2.29.4",
"mustache": "^4.2.0",
"p2psub": "^0.1.9",
"redis": "^4.6.7",
"socket.io": "^4.7.5",
"tld-extract": "^2.1.0"
},
"devDependencies": {
@@ -264,6 +266,11 @@
"@redis/client": "^1.0.0"
}
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="
},
"node_modules/@types/asn1": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.1.tgz",
@@ -272,6 +279,19 @@
"@types/node": "*"
}
},
"node_modules/@types/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
},
"node_modules/@types/cors": {
"version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "14.14.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.45.tgz",
@@ -470,6 +490,14 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"engines": {
"node": "^4.5.0 || >= 5.9"
}
},
"node_modules/bcrypt": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
@@ -709,6 +737,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -787,6 +827,63 @@
"node": ">= 0.8"
}
},
"node_modules/engine.io": {
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz",
"integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
"@types/node": ">=10.0.0",
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1"
},
"engines": {
"node": ">=10.2.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/engine.io/node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/engine.io/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1668,6 +1765,11 @@
"wrappy": "1"
}
},
"node_modules/p2psub": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/p2psub/-/p2psub-0.1.9.tgz",
"integrity": "sha512-5za6YUq6GLH+iZCqOF7YaOd13joJyqJyjp/6o3wcy9hj969EJq7sJGsU5b3MB7tjMoaHAaIKZ01j99Y9QficUQ=="
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1953,6 +2055,107 @@
"node": ">=10"
}
},
"node_modules/socket.io": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
"integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==",
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.2.0"
}
},
"node_modules/socket.io-adapter": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
"integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
"dependencies": {
"debug": "~4.3.4",
"ws": "~8.17.1"
}
},
"node_modules/socket.io-adapter/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-adapter/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-parser/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/socket.io/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@@ -2167,6 +2370,26 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+2 -1
View File
@@ -22,12 +22,13 @@
"extend": "^3.0.2",
"get-root-domain": "^0.0.1",
"jquery": "^3.7.1",
"jquery-ui": "^1.13.3",
"ldapts": "^2.12.0",
"linux-sys-user": "^1.1.8",
"moment": "^2.29.4",
"mustache": "^4.2.0",
"p2psub": "^0.1.9",
"redis": "^4.6.7",
"socket.io": "^4.7.5",
"tld-extract": "^2.1.0"
},
"license": "MIT",
+56 -46
View File
@@ -1,66 +1,76 @@
var app = {};
// app.pubsub = (function(){
// app.topics = {};
app.pubsub = (function(){
app.topics = {};
// app.subscribe = function(topic, listener){
// if(topic instanceof RegExp){
// listener.match = topic;
// topic = "__REGEX__";
// }
app.subscribe = function(topic, listener){
if(topic instanceof RegExp){
listener.match = topic;
topic = "__REGEX__";
}
// // create the topic if not yet created
// if(!app.topics[topic]) app.topics[topic] = [];
// create the topic if not yet created
if(!app.topics[topic]) app.topics[topic] = [];
// // add the listener
// app.topics[topic].push(listener);
// }
// add the listener
app.topics[topic].push(listener);
}
// app.matchTopics = function(topic){
// topic = topic || '';
// var matches = [... app.topics[topic] ? app.topics[topic] : []];
app.matchTopics = function(topic){
topic = topic || '';
var matches = [... app.topics[topic] ? app.topics[topic] : []];
// if(!app.topics['__REGEX__']) return matches;
if(!app.topics['__REGEX__']) return matches;
// for(var listener of app.topics['__REGEX__']){
// if(topic.match(listener.match)) matches.push(listener);
// }
for(var listener of app.topics['__REGEX__']){
if(topic.match(listener.match)) matches.push(listener);
}
// return matches;
// }
return matches;
}
// app.publish = function(topic, data){
app.publish = function(topic, data){
// // send the event to all listeners
// app.matchTopics(topic).forEach(function(listener){
// setTimeout(function(data, topic){
// listener(data || {}, topic);
// }, 0, data, topic);
// });
// }
// send the event to all listeners
app.matchTopics(topic).forEach(function(listener){
setTimeout(function(data, topic){
listener(data || {}, topic);
}, 0, data, topic);
});
}
// return this;
// })(app);
return this;
})(app);
// app.socket = (function(app){
// var socket = io();
// // socket.emit('chat message', $('#m').val());
// socket.on('P2PSub', function(msg){
// msg.data.__noSocket = true;
// app.publish(msg.topic, msg.data);
// });
app.socket = (function(app){
// $.getScript('/socket.io/socket.io.js')
// <script type="text/javascript" src="/socket.io/socket.io.js"></script>
var socket;
$(document).ready(function(){
socket = io({
auth: {
token: app.auth.getToken()
}
});
// socket.emit('chat message', $('#m').val());
socket.on('P2PSub', function(msg){
msg.data.__noSocket = true;
app.publish(msg.topic, msg.data);
});
// app.subscribe(/./g, function(data, topic){
// // console.log('local_pubs', data, topic)
// if(data.__noSocket) return;
// // console.log('local_pubs 2', data, topic)
app.subscribe(/./g, function(data, topic){
// console.log('local_pubs', data, topic)
if(data.__noSocket) return;
// console.log('local_pubs 2', data, topic)
// socket.emit('P2PSub', { topic, data })
// });
socket.emit('P2PSub', { topic, data });
});
})
// return socket;
return socket;
// })(app);
})(app);
app.api = (function(app){
var baseURL = '/api/'
+19
View File
@@ -0,0 +1,19 @@
'use strict';
const router = require('express').Router();
const conf = require('../conf');
const middleware = require('../middleware/auth');
// API routes for authentication.
router.use('/auth', require('./auth'));
// API routes for working with users. All endpoints need to be have valid user.
router.use('/user', middleware.auth, require('./user'));
// API routes for working with hosts. All endpoints need to be have valid user.
router.use('/host', middleware.auth, require('./host'));
// API routes for working with hosts. All endpoints need to be have valid user.
router.use('/cert', middleware.auth, require('./cert'));
module.exports = router;
+2 -38
View File
@@ -1,9 +1,7 @@
'use strict';
const router = require('express').Router();
const {User} = require('../models/user');
const {Auth, AuthToken} = require('../models/auth');
const { Auth } = require('../controller/auth');
router.post('/login', async function(req, res, next){
try{
@@ -11,6 +9,7 @@ router.post('/login', async function(req, res, next){
return res.json({
login: true,
token: auth.token.token,
message:`${req.body.username} logged in!`,
});
}catch(error){
next(error);
@@ -29,39 +28,4 @@ router.all('/logout', async function(req, res, next){
}
});
router.post('/invite/:token', async function(req, res, next) {
try{
req.body.token = req.params.token;
let user = await User.addByInvite(req.body);
let token = await AuthToken.add(user);
return res.json({
user: user.username,
token: token.token
});
}catch(error){
next(error);
}
});
module.exports = router;
/*
verify public ssh key
*/
// router.post('/verifykey', async function(req, res){
// let key = req.body.key;
// try{
// return res.json({
// info: await Users.verifyKey(key)
// });
// }catch(error){
// return res.status(400).json({
// message: 'Key is not a public key file!'
// });
// }
// });
-1
View File
@@ -3,7 +3,6 @@
const router = require('express').Router();
const {Host} = require('../models/host');
const Model = Host;
router.get('/', async function(req, res, next){
+18 -2
View File
@@ -1,13 +1,29 @@
'use strict';
const path = require('path');
const express = require('express');
const router = require('express').Router();
const conf = require('../conf')
const middleware = require('../middleware/auth');
const conf = require('../conf');
const values ={
title: conf.environment !== 'production' ? `<i class="fa-brands fa-dev"></i>` : ''
}
// List of front end node modules to be served
const frontEndModules = ['bootstrap', 'mustache', 'jquery', '@fortawesome',
'moment',
];
// Server front end modules
// https://stackoverflow.com/a/55700773/3140931
frontEndModules.forEach(dep => {
router.use(`/static-modules/${dep}`, express.static(path.join(__dirname, `../node_modules/${dep}`)))
});
// Have express server static content( images, CSS, browser JS) from the public
// local folder.
router.use('/static', express.static(path.join(__dirname, '../public')))
router.get('/', async function(req, res, next) {
res.render('hosts', {...values});
});
+49
View File
@@ -0,0 +1,49 @@
'use strict';
const ps = require('../controller/pubsub');
function ModelPs(model){
const Model = model.constructor.name === 'Function' ? model : model.constructor
function getIndex(req, res){
if(model[Model._key]) return model[Model._key];
if(req && req[Model._key]) return req[Model._key];
if(res && res[Model._key]) return res[Model._key];
}
function publish(prop, res, req){
if(!['add', 'create', 'update', 'remove'].includes(prop)) return;
ps.publish(`model:${Model.name}:${prop}:${getIndex(res, req)}`, res);
}
return new Proxy(model, {
construct(target, args) {
let instance = ModelPs(new model(...args));
return instance;
},
get(target, propKey, receiver) {
if(propKey == 'constructor') return target.constructor;
if(propKey === 'isproxy') return 'YESSSSSSSSS'
const targetValue = Reflect.get(target, propKey, receiver);
if (typeof targetValue === 'function') {
return function(...args){
let res = targetValue.apply(this, args); // (A)
if(targetValue.constructor.name === 'AsyncFunction'){
res.then(function(res){
publish(propKey, res, ...args);
});
}else{
publish(propKey, res, ...args)
}
return res;
}
} else {
return targetValue;
}
}
});
}
module.exports = ModelPs;
+5 -2
View File
@@ -22,7 +22,6 @@ class Table{
static async get(index){
try{
if(typeof index === 'object'){
index = index[this._key];
}
@@ -43,7 +42,7 @@ class Table{
// back to native values.
result = objValidate.parseFromString(this._keyMap, result);
return new this.prototype.constructor(result);
return new this(result);
}catch(error){
throw error;
@@ -84,6 +83,10 @@ class Table{
return out;
}
static async create(...args){
return this.add(...args);
}
static async add(data){
// Add a entry to this redis table.
try{
+1 -2
View File
@@ -10,9 +10,8 @@
<link rel='stylesheet' href='/static/css/styles.css' />
<!-- Scripts are placed here -->
<!-- <script type="text/javascript" src="/socket.io/socket.io.js"></script> -->
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src='/static-modules/jquery/dist/jquery.js'></script>
<script type="text/javascript" src='/static-modules/jquery-ui/dist/jquery-ui.min.js'></script>
<!-- <script type="text/javascript" src="/static/lib/js/popper-1.16.0.min.js"></script> -->
<script type="text/javascript" src="/static-modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/static-modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>