diff --git a/index.js b/index.js index 9016b03..84a2422 100644 --- a/index.js +++ b/index.js @@ -4,9 +4,11 @@ const MongoClient = require('mongodb').MongoClient const fs = require('fs') const bodyParser = require('body-parser') const cors = require('cors') +const AutoEncrypt = require('@small-tech/auto-encrypt') const https = require('https') const morgan = require('morgan') const history = require('connect-history-api-fallback') +const { onShutdown } = require('node-graceful-shutdown') const routes = require('./routes') const pub = require('./pub') @@ -63,6 +65,10 @@ app.use(function (err, req, res, next) { res.status(500).send('An error occurred while processing the request') }) +const server = process.env.NODE_ENV === 'production' + ? AutoEncrypt.https.createServer({ domains: ['gup.pe'] }, app) + : https.createServer(sslOptions, app) + client.connect({ useNewUrlParser: true }) .then(() => { console.log('Connected successfully to db') @@ -77,10 +83,18 @@ client.connect({ useNewUrlParser: true }) return store.setup(DOMAIN, dummy) }) .then(() => { - https.createServer(sslOptions, app).listen(app.get('port-https'), function () { - console.log('Express server listening on port ' + app.get('port-https')) + server.listen(app.get('port-https'), function () { + console.log('Guppe server listening on port ' + app.get('port-https')) }) }) .catch(err => { throw new Error(err) }) + +onShutdown(async () => { + await client.close() + await new Promise((resolve, reject) => { + server.close(err => (err ? reject(err) : resolve())) + }) + console.log('Guppe server closed') +}) diff --git a/package-lock.json b/package-lock.json index 57b736c..21077fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,26 @@ "js-tokens": "^4.0.0" } }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, + "@small-tech/auto-encrypt": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@small-tech/auto-encrypt/-/auto-encrypt-2.0.5.tgz", + "integrity": "sha512-Qfm3BckBsf7Rf1Qys60pwHOsLA0IEzYDig6xM69psXuWowwgnjFSlylKQvr9bal/DVlMBbo559jCpBFY40EZuQ==", + "requires": { + "bent": "github:aral/bent#errors-with-response-headers", + "encodeurl": "^1.0.2", + "fs-extra": "^8.1.0", + "jose": "^1.24.0", + "moment": "^2.24.0", + "node-forge": "^0.10.0", + "ocsp": "^1.2.0", + "server-destroy": "^1.0.1" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -158,6 +178,32 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "asn1.js-rfc2560": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/asn1.js-rfc2560/-/asn1.js-rfc2560-4.0.6.tgz", + "integrity": "sha512-ysf48ni+f/efNPilq4+ApbifUPcSW/xbDeQAh055I+grr2gXgNRQqHew7kkO70WSMQ2tEOURVwsK+dJqUNjIIg==", + "requires": { + "asn1.js-rfc5280": "^2.0.0" + } + }, + "asn1.js-rfc5280": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/asn1.js-rfc5280/-/asn1.js-rfc5280-2.0.1.tgz", + "integrity": "sha512-1e2ypnvTbYD/GdxWK77tdLBahvo1fZUHlQJqAVUuZWdYj0rdjGcf2CWYUtbsyRYpYUMwMWLZFUtLxog8ZXTrcg==", + "requires": { + "asn1.js": "^4.5.0" + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -175,6 +221,11 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -286,12 +337,33 @@ "tweetnacl": "^0.14.3" } }, + "bent": { + "version": "github:aral/bent#16a959683c6916204c28a1c870cb7b399c9215a9", + "from": "github:aral/bent#errors-with-response-headers", + "requires": { + "bytesish": "^0.4.1", + "caseless": "~0.12.0", + "is-stream": "^2.0.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + } + } + }, "binary-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -353,6 +425,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "bytesish": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/bytesish/-/bytesish-0.4.4.tgz", + "integrity": "sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==" + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1494,6 +1571,16 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1605,8 +1692,7 @@ "graceful-fs": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, "har-schema": { "version": "2.0.0", @@ -2069,6 +2155,14 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "jose": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-1.28.0.tgz", + "integrity": "sha512-JmfDRzt/HSj8ipd9TsDtEHoLUnLYavG+7e8F6s1mx2jfVSfXOTaFQsJUydbjJpTnTDHP1+yKL9Ke7ktS/a0Eiw==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2117,6 +2211,14 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2391,6 +2493,11 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2436,6 +2543,11 @@ "minimist": "0.0.8" } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, "mongodb": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", @@ -2512,6 +2624,16 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, + "node-graceful-shutdown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/node-graceful-shutdown/-/node-graceful-shutdown-1.1.0.tgz", + "integrity": "sha512-g1tq/R8ie/At5xRHGfF+chTge1jVPxf1NEClLpZIPxOPi6PJ9II81T35ms1u+s4N/mqOCp60CFd+ps+DIWRigQ==" + }, "nodemon": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.3.tgz", @@ -3405,6 +3527,18 @@ "has": "^1.0.3" } }, + "ocsp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ocsp/-/ocsp-1.2.0.tgz", + "integrity": "sha1-RpoXdrRX3uZ+sCAUCMGUa6xAdsw=", + "requires": { + "asn1.js": "^4.8.0", + "asn1.js-rfc2560": "^4.0.0", + "asn1.js-rfc5280": "^2.0.0", + "async": "^1.5.2", + "simple-lru-cache": "0.0.2" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -4130,6 +4264,11 @@ "send": "0.17.1" } }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -4179,6 +4318,11 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-lru-cache": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz", + "integrity": "sha1-1ZzDoZPBpdAyD4Tucy9uRxPlEd0=" + }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -4772,6 +4916,11 @@ "crypto-random-string": "^1.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 7c73b90..56aae61 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Decentralized social groups with ActivityPub, NodeJS, Express, Vue, and Mongodb", "main": "index.js", "dependencies": { + "@small-tech/auto-encrypt": "2.0.5", "body-parser": "^1.18.3", "connect-history-api-fallback": "^1.6.0", "cors": "^2.8.4", @@ -12,6 +13,7 @@ "http-signature": "github:wmurphyrd/node-http-signature#9c02eeb", "mongodb": "^3.3.2", "morgan": "^1.9.1", + "node-graceful-shutdown": "1.1.0", "request": "^2.88.0", "request-promise-native": "^1.0.7" }, diff --git a/routes/user.js b/routes/user.js index 0000481..abeb7ef 100644 --- a/routes/user.js +++ b/routes/user.js @@ -9,6 +9,7 @@ router.get('/', net.validators.jsonld, function (req, res) { const db = req.app.get('db') db.collection('streams') .aggregate([ + { $sort: { _id: -1 } }, // start from most recent { $limit: 10000 }, // don't traverse the entire history { $match: { type: 'Announce' } }, { $group: { _id: '$actor', postCount: { $sum: 1 } } }, @@ -18,7 +19,7 @@ router.get('/', net.validators.jsonld, function (req, res) { { $project: { _id: 0, _meta: 0, actor: 0 } } ]) .sort({ postCount: -1 }) - .limit(Number.parseInt(req.query.n) || 20) + .limit(Number.parseInt(req.query.n) || 50) .toArray() .then(groups => { console.log(JSON.stringify(groups)); return groups }) .then(groups => res.json(groups))