@sockethub/server 5.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +165 -0
- package/README.md +136 -0
- package/bin/sockethub +3 -0
- package/coverage/tmp/coverage-93126-1649152190997-0.json +1 -0
- package/dist/bootstrap/init.d.ts +18 -0
- package/dist/bootstrap/init.js +63 -0
- package/dist/bootstrap/init.js.map +1 -0
- package/dist/bootstrap/platforms.js +75 -0
- package/dist/common.d.ts +3 -0
- package/dist/common.js +20 -0
- package/dist/common.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +102 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +10 -0
- package/dist/crypto.js +38 -0
- package/dist/crypto.js.map +1 -0
- package/dist/defaults.json +28 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/janitor.d.ts +15 -0
- package/dist/janitor.js +89 -0
- package/dist/janitor.js.map +1 -0
- package/dist/listener.d.ts +28 -0
- package/dist/listener.js +91 -0
- package/dist/listener.js.map +1 -0
- package/dist/middleware/create-activity-object.d.ts +6 -0
- package/dist/middleware/create-activity-object.js +19 -0
- package/dist/middleware/create-activity-object.js.map +1 -0
- package/dist/middleware/expand-activity-stream.d.ts +2 -0
- package/dist/middleware/expand-activity-stream.js +33 -0
- package/dist/middleware/expand-activity-stream.js.map +1 -0
- package/dist/middleware/expand-activity-stream.test.data.d.ts +480 -0
- package/dist/middleware/expand-activity-stream.test.data.js +360 -0
- package/dist/middleware/expand-activity-stream.test.data.js.map +1 -0
- package/dist/middleware/store-credentials.d.ts +3 -0
- package/dist/middleware/store-credentials.js +19 -0
- package/dist/middleware/store-credentials.js.map +1 -0
- package/dist/middleware/validate.d.ts +2 -0
- package/dist/middleware/validate.js +58 -0
- package/dist/middleware/validate.js.map +1 -0
- package/dist/middleware/validate.test.data.d.ts +532 -0
- package/dist/middleware/validate.test.data.js +263 -0
- package/dist/middleware/validate.test.data.js.map +1 -0
- package/dist/middleware.d.ts +10 -0
- package/dist/middleware.js +54 -0
- package/dist/middleware.js.map +1 -0
- package/dist/platform-instance.d.ts +77 -0
- package/dist/platform-instance.js +211 -0
- package/dist/platform-instance.js.map +1 -0
- package/dist/platform.d.ts +6 -0
- package/dist/platform.js +187 -0
- package/dist/platform.js.map +1 -0
- package/dist/process-manager.d.ts +11 -0
- package/dist/process-manager.js +78 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/routes.d.ts +13 -0
- package/dist/routes.js +83 -0
- package/dist/routes.js.map +1 -0
- package/dist/sockethub.d.ts +39 -0
- package/dist/sockethub.js +119 -0
- package/dist/sockethub.js.map +1 -0
- package/dist/store.d.ts +5 -0
- package/dist/store.js +17 -0
- package/dist/store.js.map +1 -0
- package/package.json +103 -0
- package/sockethub.config.example.json +33 -0
- package/src/bootstrap/init.d.ts +8 -0
- package/src/bootstrap/init.ts +83 -0
- package/src/bootstrap/platforms.js +75 -0
- package/src/common.test.ts +54 -0
- package/src/common.ts +14 -0
- package/src/config.d.ts +2 -0
- package/src/config.test.ts +28 -0
- package/src/config.ts +94 -0
- package/src/crypto.d.ts +5 -0
- package/src/crypto.test.ts +41 -0
- package/src/crypto.ts +41 -0
- package/src/defaults.json +28 -0
- package/src/index.ts +28 -0
- package/src/janitor.d.ts +8 -0
- package/src/janitor.ts +89 -0
- package/src/listener.ts +79 -0
- package/src/middleware/create-activity-object.test.ts +10 -0
- package/src/middleware/create-activity-object.ts +13 -0
- package/src/middleware/expand-activity-stream.test.data.ts +365 -0
- package/src/middleware/expand-activity-stream.test.ts +78 -0
- package/src/middleware/expand-activity-stream.ts +27 -0
- package/src/middleware/store-credentials.test.ts +73 -0
- package/src/middleware/store-credentials.ts +16 -0
- package/src/middleware/validate.d.ts +1 -0
- package/src/middleware/validate.test.data.ts +261 -0
- package/src/middleware/validate.test.ts +83 -0
- package/src/middleware/validate.ts +49 -0
- package/src/middleware.d.ts +21 -0
- package/src/middleware.test.ts +154 -0
- package/src/middleware.ts +52 -0
- package/src/platform-instance.test.ts +237 -0
- package/src/platform-instance.ts +242 -0
- package/src/platform.ts +191 -0
- package/src/process-manager.ts +64 -0
- package/src/routes.test.ts +100 -0
- package/src/routes.ts +98 -0
- package/src/sockethub.d.ts +1 -0
- package/src/sockethub.ts +165 -0
- package/src/store.test.ts +28 -0
- package/src/store.ts +17 -0
- package/test/init-suite.js +41 -0
- package/test/queue.functional.test.js +0 -0
- package/test/sockethub-suite.js +25 -0
- package/tsconfig.json +18 -0
- package/views/examples/dummy.ejs +93 -0
- package/views/examples/feeds.ejs +90 -0
- package/views/examples/irc.ejs +239 -0
- package/views/examples/shared.js +72 -0
- package/views/examples/xmpp.ejs +191 -0
- package/views/index.ejs +17 -0
package/package.json
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sockethub/server",
|
|
3
|
+
"description": "A polyglot messaging service, server libraries",
|
|
4
|
+
"version": "5.0.0-alpha.3",
|
|
5
|
+
"private": false,
|
|
6
|
+
"author": "Nick Jennings <nick@silverbucket.net>",
|
|
7
|
+
"license": "LGPL-3.0+",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"bin": "bin/sockethub",
|
|
10
|
+
"preferGlobal": true,
|
|
11
|
+
"keywords": [
|
|
12
|
+
"sockethub",
|
|
13
|
+
"messaging",
|
|
14
|
+
"polyglot",
|
|
15
|
+
"unhosted",
|
|
16
|
+
"apis",
|
|
17
|
+
"api",
|
|
18
|
+
"protocols",
|
|
19
|
+
"protocol",
|
|
20
|
+
"irc",
|
|
21
|
+
"xmpp",
|
|
22
|
+
"facebook",
|
|
23
|
+
"rss",
|
|
24
|
+
"atom",
|
|
25
|
+
"twitter",
|
|
26
|
+
"smtp",
|
|
27
|
+
"imap",
|
|
28
|
+
"email"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/sockethub/sockethub.git",
|
|
33
|
+
"directory": "packages/server"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://sockethub.org",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@sockethub/activity-streams": "^4.4.0-alpha.3",
|
|
38
|
+
"@sockethub/client": "^5.0.0-alpha.3",
|
|
39
|
+
"@sockethub/schemas": "^3.0.0-alpha.3",
|
|
40
|
+
"body-parser": "^1.19.0",
|
|
41
|
+
"bull": "^4.0.0",
|
|
42
|
+
"debug": "^4.3.1",
|
|
43
|
+
"ejs": "^3.0.1",
|
|
44
|
+
"express": "^4.17.1",
|
|
45
|
+
"findup-sync": "^5.0.0",
|
|
46
|
+
"jquery": "^3.4.1",
|
|
47
|
+
"nconf": "^0.11.2",
|
|
48
|
+
"npm": "8.5.4",
|
|
49
|
+
"object-hash": "^3.0.0",
|
|
50
|
+
"secure-store-redis": "^1.4.7",
|
|
51
|
+
"socket.io": "^4.0.1",
|
|
52
|
+
"urijs": "^1.19.2"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"clean": "npx rimraf dist coverage",
|
|
56
|
+
"clean:deps": "npx rimraf node_modules",
|
|
57
|
+
"compliance": "yarn run lint && yarn run test && yarn run coverage",
|
|
58
|
+
"test": "c8 -x src/bootstrap -x \"src/**/*.test.*\" mocha -r ts-node/register src/*.test.ts src/**/*.test.ts",
|
|
59
|
+
"coverage": "c8 check-coverage --statements 90 --branches 80 --functions 90 --lines 90",
|
|
60
|
+
"start": "DEBUG=sockethub* ./bin/sockethub",
|
|
61
|
+
"dev": "yarn run build && DEBUG=sockethub* ./bin/sockethub --examples",
|
|
62
|
+
"lint": "eslint \"**/*.ts\" ./bin/sockethub",
|
|
63
|
+
"lint:fix": "eslint --fix \"**/*.ts\" ./bin/sockethub",
|
|
64
|
+
"build": "npx rimraf dist && tsc && cp ./src/defaults.json ./dist/defaults.json && cp src/bootstrap/platforms.js dist/bootstrap/"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">= 12.4.0"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/body-parser": "1.19.2",
|
|
71
|
+
"@types/chai": "4.3.0",
|
|
72
|
+
"@types/debug": "4.1.7",
|
|
73
|
+
"@types/ejs": "3.1.0",
|
|
74
|
+
"@types/eslint": "8.4.1",
|
|
75
|
+
"@types/express": "4.17.13",
|
|
76
|
+
"@types/jquery": "3.5.13",
|
|
77
|
+
"@types/mocha": "9.1.0",
|
|
78
|
+
"@types/nconf": "0.10.1",
|
|
79
|
+
"@types/node": "17.0.13",
|
|
80
|
+
"@types/object-hash": "2.2.1",
|
|
81
|
+
"@types/proxyquire": "1.3.28",
|
|
82
|
+
"@types/sinon": "10.0.11",
|
|
83
|
+
"@types/urijs": "1.19.18",
|
|
84
|
+
"@typescript-eslint/parser": "5.12.1",
|
|
85
|
+
"c8": "7.11.0",
|
|
86
|
+
"chai": "4.3.6",
|
|
87
|
+
"eslint": "8.9.0",
|
|
88
|
+
"eslint-cli": "1.1.1",
|
|
89
|
+
"jaribu": "2.2.3",
|
|
90
|
+
"mocha": "9.2.1",
|
|
91
|
+
"proxyquire": "2.1.3",
|
|
92
|
+
"sinon": "13.0.1",
|
|
93
|
+
"ts-node": "10.5.0",
|
|
94
|
+
"typescript": "4.5.5"
|
|
95
|
+
},
|
|
96
|
+
"optionalDependencies": {
|
|
97
|
+
"@sockethub/platform-dummy": "^3.0.0-alpha.3",
|
|
98
|
+
"@sockethub/platform-feeds": "^3.0.0-alpha.3",
|
|
99
|
+
"@sockethub/platform-irc": "^4.0.0-alpha.3",
|
|
100
|
+
"@sockethub/platform-xmpp": "^5.0.0-alpha.3"
|
|
101
|
+
},
|
|
102
|
+
"gitHead": "f02238a478b7ffd3f31d8deea292eb67e630a86b"
|
|
103
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"activity-streams": {
|
|
3
|
+
"opts": {
|
|
4
|
+
"specialObjs": [ "credentials" ]
|
|
5
|
+
}
|
|
6
|
+
},
|
|
7
|
+
"examples": {
|
|
8
|
+
"enabled": false,
|
|
9
|
+
"secret": 1234567890
|
|
10
|
+
},
|
|
11
|
+
"sockethub": {
|
|
12
|
+
"port": 10550,
|
|
13
|
+
"host": "localhost",
|
|
14
|
+
"path": "/sockethub"
|
|
15
|
+
},
|
|
16
|
+
"log_file": "",
|
|
17
|
+
"platforms": [
|
|
18
|
+
"@sockethub/platform-dummy",
|
|
19
|
+
"@sockethub/platform-feeds",
|
|
20
|
+
"@sockethub/platform-irc",
|
|
21
|
+
"@sockethub/platform-xmpp"
|
|
22
|
+
],
|
|
23
|
+
"public": {
|
|
24
|
+
"protocol": "http",
|
|
25
|
+
"host": "localhost",
|
|
26
|
+
"port": 10550,
|
|
27
|
+
"path": "/"
|
|
28
|
+
},
|
|
29
|
+
"redis": {
|
|
30
|
+
"host": "127.0.0.1",
|
|
31
|
+
"port": 6379
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
|
|
3
|
+
import config from '../config';
|
|
4
|
+
import platformLoad from './platforms';
|
|
5
|
+
|
|
6
|
+
const log = debug('sockethub:server:bootstrap:init');
|
|
7
|
+
log('running init routines');
|
|
8
|
+
|
|
9
|
+
const packageJSON = require('./../../package.json');
|
|
10
|
+
const platforms = platformLoad(config.get('platforms'));
|
|
11
|
+
|
|
12
|
+
if (config.get('info')) {
|
|
13
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
14
|
+
console.log('sockethub ' + packageJSON.version);
|
|
15
|
+
console.log();
|
|
16
|
+
|
|
17
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
18
|
+
console.log('websocket: ws://' + config.get('sockethub:host') + ':'
|
|
19
|
+
+ config.get('sockethub:port')
|
|
20
|
+
+ config.get('sockethub:path'));
|
|
21
|
+
|
|
22
|
+
console.log();
|
|
23
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
24
|
+
console.log('examples: ' + (config.get('examples:enabled') ?
|
|
25
|
+
'http://' +
|
|
26
|
+
config.get('public:host') + ':' + config.get('public:port') + config.get('public:path')
|
|
27
|
+
: 'disabled'));
|
|
28
|
+
|
|
29
|
+
console.log();
|
|
30
|
+
if (config.get('redis:url')) {
|
|
31
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
32
|
+
console.log('redis URL: ' + config.get('redis:url'));
|
|
33
|
+
} else {
|
|
34
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
35
|
+
console.log('redis: ' + config.get('redis:host') + ':' + config.get('redis:port'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log();
|
|
39
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
40
|
+
console.log('platforms: ' + Array.from(platforms.keys()).join(', '));
|
|
41
|
+
|
|
42
|
+
if (platforms.size > 0) {
|
|
43
|
+
for (let platform of platforms.values()) {
|
|
44
|
+
console.log();
|
|
45
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
46
|
+
console.log(platform.moduleName);
|
|
47
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
48
|
+
console.log(' name: ' + platform.id + ' version: ' + platform.version);
|
|
49
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
50
|
+
console.log(' AS types: ' + platform.types.join(', '));
|
|
51
|
+
}
|
|
52
|
+
console.log();
|
|
53
|
+
process.exit();
|
|
54
|
+
} else {
|
|
55
|
+
console.log();
|
|
56
|
+
process.exit();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
log('finished init routines');
|
|
61
|
+
|
|
62
|
+
export interface IInitObject {
|
|
63
|
+
version: string,
|
|
64
|
+
platforms: Map<string, {
|
|
65
|
+
id: string,
|
|
66
|
+
moduleName: string,
|
|
67
|
+
config: {
|
|
68
|
+
persist?: boolean
|
|
69
|
+
},
|
|
70
|
+
schemas: {
|
|
71
|
+
credentials?: object,
|
|
72
|
+
messages?: object
|
|
73
|
+
},
|
|
74
|
+
version: string,
|
|
75
|
+
types: Array<string>
|
|
76
|
+
}>,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const init: IInitObject = {
|
|
80
|
+
version: packageJSON.version,
|
|
81
|
+
platforms: platforms
|
|
82
|
+
};
|
|
83
|
+
export default init;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bootstrap/platforms.js
|
|
3
|
+
*
|
|
4
|
+
* A Singleton responsible for finding and loading all valid Sockethub
|
|
5
|
+
* platforms, and whitelisting or blacklisting (or neither) based on the
|
|
6
|
+
* config.
|
|
7
|
+
*/
|
|
8
|
+
const debug = require('debug'),
|
|
9
|
+
schemas = require('@sockethub/schemas').default;
|
|
10
|
+
|
|
11
|
+
const log = debug('sockethub:server:bootstrap:platforms');
|
|
12
|
+
|
|
13
|
+
log('loading platforms');
|
|
14
|
+
|
|
15
|
+
// if the platform schema lists valid types it implements (essentially methods/verbs for
|
|
16
|
+
// Sockethub to call) then add it to the supported types list.
|
|
17
|
+
function platformListsSupportedTypes(p) {
|
|
18
|
+
return ((p.schema.messages.properties) && (p.schema.messages.properties.type) &&
|
|
19
|
+
(p.schema.messages.properties.type.enum) &&
|
|
20
|
+
(p.schema.messages.properties.type.enum.length > 0));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = function platformLoad(platformsList, requireModule) {
|
|
24
|
+
if (!requireModule) {
|
|
25
|
+
requireModule = require;
|
|
26
|
+
}
|
|
27
|
+
// load platforms from config.platforms
|
|
28
|
+
const platforms = new Map();
|
|
29
|
+
|
|
30
|
+
if (platformsList.length <= 0) {
|
|
31
|
+
throw new Error('No platforms defined. Please check your sockethub.config.json');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (let moduleName of platformsList) {
|
|
35
|
+
log(`loading ${moduleName}`);
|
|
36
|
+
// try to load platform
|
|
37
|
+
// eslint-disable-next-line security-node/detect-non-literal-require-calls
|
|
38
|
+
const P = requireModule(moduleName);
|
|
39
|
+
const p = new P();
|
|
40
|
+
let types = [];
|
|
41
|
+
|
|
42
|
+
const err = schemas.validatePlatformSchema(p.schema);
|
|
43
|
+
if (err) {
|
|
44
|
+
throw new Error(`${moduleName} ${err}`);
|
|
45
|
+
} else if (typeof p.config !== 'object') {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`${moduleName} platform must have a config property that is an object.`);
|
|
48
|
+
} else {
|
|
49
|
+
if (p.schema.credentials) {
|
|
50
|
+
// register the platforms credentials schema
|
|
51
|
+
types.push('credentials');
|
|
52
|
+
} else {
|
|
53
|
+
p.config.noCredentials = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (platformListsSupportedTypes(p)) {
|
|
58
|
+
types = [...types, ...p.schema.messages.properties.type.enum];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const platformName = p.schema.name;
|
|
62
|
+
platforms.set(platformName, {
|
|
63
|
+
id: platformName,
|
|
64
|
+
moduleName: moduleName,
|
|
65
|
+
config: p.config,
|
|
66
|
+
schemas: {
|
|
67
|
+
credentials: p.schema.credentials || {},
|
|
68
|
+
messages: p.schema.messages || {}
|
|
69
|
+
},
|
|
70
|
+
version: p.schema.version,
|
|
71
|
+
types: types
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return platforms;
|
|
75
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import proxyquire from 'proxyquire';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import * as sinon from 'sinon';
|
|
4
|
+
|
|
5
|
+
import { decryptJobData, getPlatformId } from './common';
|
|
6
|
+
import crypto from './crypto';
|
|
7
|
+
|
|
8
|
+
proxyquire.noPreserveCache();
|
|
9
|
+
proxyquire.noCallThru();
|
|
10
|
+
|
|
11
|
+
describe("getPlatformId", () => {
|
|
12
|
+
let cryptoHashStub: any;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
cryptoHashStub = sinon.stub(crypto, 'hash');
|
|
16
|
+
cryptoHashStub.returnsArg(0);
|
|
17
|
+
proxyquire('./common', { crypto: { hash: cryptoHashStub }});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
cryptoHashStub.restore();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('generates platform hash', () => {
|
|
25
|
+
expect(getPlatformId('foo')).to.be.equal('foo');
|
|
26
|
+
sinon.assert.calledOnce(cryptoHashStub);
|
|
27
|
+
sinon.assert.calledWith(cryptoHashStub, 'foo');
|
|
28
|
+
});
|
|
29
|
+
it('generates platform + actor hash', () => {
|
|
30
|
+
expect(getPlatformId('foo', 'bar')).to.be.equal('foobar');
|
|
31
|
+
sinon.assert.calledOnce(cryptoHashStub);
|
|
32
|
+
sinon.assert.calledWith(cryptoHashStub, 'foobar');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("decryptJobData", () => {
|
|
37
|
+
let cryptoDecryptStub: any;
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
cryptoDecryptStub = sinon.stub(crypto, 'decrypt');
|
|
41
|
+
cryptoDecryptStub.returnsArg(0);
|
|
42
|
+
proxyquire('./common', { crypto: { hash: cryptoDecryptStub }});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
cryptoDecryptStub.restore();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("decrypts and returns expected object", () => {
|
|
50
|
+
const jobData = {data:{title:"foo", msg:'encryptedjobdata', sessionId:'foobar'}};
|
|
51
|
+
const secret = 'secretstring';
|
|
52
|
+
expect(decryptJobData(jobData, secret)).to.be.eql(jobData.data);
|
|
53
|
+
});
|
|
54
|
+
});
|
package/src/common.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import crypto from "./crypto";
|
|
2
|
+
import { JobDataDecrypted, JobEncrypted } from "./sockethub";
|
|
3
|
+
|
|
4
|
+
export function getPlatformId(platform: string, actor?: string): string {
|
|
5
|
+
return actor ? crypto.hash(platform + actor) : crypto.hash(platform);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function decryptJobData(job: JobEncrypted, secret: string): JobDataDecrypted {
|
|
9
|
+
return {
|
|
10
|
+
title: job.data.title,
|
|
11
|
+
msg: crypto.decrypt(job.data.msg, secret),
|
|
12
|
+
sessionId: job.data.sessionId
|
|
13
|
+
};
|
|
14
|
+
}
|
package/src/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
|
|
3
|
+
import { Config } from './config';
|
|
4
|
+
|
|
5
|
+
describe('config', () => {
|
|
6
|
+
|
|
7
|
+
it('loads default values', () => {
|
|
8
|
+
const config = new Config();
|
|
9
|
+
expect(config).to.have.property('get');
|
|
10
|
+
expect(config.get('sockethub:host')).to.eql('localhost');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('overrides from env', () => {
|
|
14
|
+
const hostname = 'a host string';
|
|
15
|
+
process.env = { HOST: hostname };
|
|
16
|
+
const config = new Config();
|
|
17
|
+
expect(config).to.have.property('get');
|
|
18
|
+
expect(config.get('sockethub:host')).to.eql(hostname);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('defaults to redis config', () => {
|
|
22
|
+
process.env = { REDIS_URL: '' };
|
|
23
|
+
const config = new Config();
|
|
24
|
+
expect(config).to.have.property('get');
|
|
25
|
+
expect(config.get('redis')).to.eql(
|
|
26
|
+
{"host": "127.0.0.1", "port": 6379});
|
|
27
|
+
});
|
|
28
|
+
});
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import nconf from 'nconf';
|
|
2
|
+
import { debug } from 'debug';
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
|
|
5
|
+
const log = debug('sockethub:server:bootstrap:config');
|
|
6
|
+
|
|
7
|
+
export class Config {
|
|
8
|
+
constructor() {
|
|
9
|
+
log('initializing config');
|
|
10
|
+
// assign config loading priorities (command-line, environment, cfg, defaults)
|
|
11
|
+
nconf.argv({
|
|
12
|
+
'info': {
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
describe: 'Display Sockethub runtime information'
|
|
15
|
+
},
|
|
16
|
+
'examples': {
|
|
17
|
+
type: 'boolean',
|
|
18
|
+
describe: 'Enable the examples pages served at [host]:[port]/examples'
|
|
19
|
+
},
|
|
20
|
+
'config': {
|
|
21
|
+
alias: 'c',
|
|
22
|
+
default: '',
|
|
23
|
+
describe: 'Path to sockethub.config.json'
|
|
24
|
+
},
|
|
25
|
+
'port': {
|
|
26
|
+
alias: 'sockethub.port'
|
|
27
|
+
},
|
|
28
|
+
'host': {
|
|
29
|
+
alias: 'sockethub.host'
|
|
30
|
+
},
|
|
31
|
+
'redis_host': {
|
|
32
|
+
alias: 'redis.host'
|
|
33
|
+
},
|
|
34
|
+
'redis_port': {
|
|
35
|
+
alias: 'redis.port'
|
|
36
|
+
},
|
|
37
|
+
'redis_url': {
|
|
38
|
+
alias: 'redis.url'
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
nconf.env();
|
|
42
|
+
|
|
43
|
+
// get value of flags defined by any command-line params
|
|
44
|
+
const examples = nconf.get('examples');
|
|
45
|
+
|
|
46
|
+
// Load the main config
|
|
47
|
+
let configFile = nconf.get('config');
|
|
48
|
+
if (configFile) {
|
|
49
|
+
if (! fs.existsSync(configFile)) {
|
|
50
|
+
throw new Error(`Config file not found: ${configFile}`);
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
configFile = __dirname + '/../sockethub.config.json';
|
|
54
|
+
}
|
|
55
|
+
nconf.file(configFile);
|
|
56
|
+
|
|
57
|
+
// only override config file if explicitly mentioned in command-line params
|
|
58
|
+
nconf.set('examples:enabled', (examples ? true : nconf.get('examples:enabled')));
|
|
59
|
+
|
|
60
|
+
// load defaults
|
|
61
|
+
const defaults: object = require(__dirname + '/defaults.json');
|
|
62
|
+
nconf.defaults(defaults);
|
|
63
|
+
|
|
64
|
+
nconf.required(['platforms']);
|
|
65
|
+
|
|
66
|
+
function defaultEnvParams(host: string, port: string | number, prop: string) {
|
|
67
|
+
nconf.set(prop + ':host', host);
|
|
68
|
+
nconf.set(prop + ':port', port);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
defaultEnvParams(
|
|
72
|
+
process.env.HOST || nconf.get('sockethub:host'),
|
|
73
|
+
process.env.PORT || nconf.get('sockethub:port'),
|
|
74
|
+
'sockethub'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
defaultEnvParams(
|
|
78
|
+
process.env.REDIS_HOST || nconf.get('redis:host'),
|
|
79
|
+
process.env.REDIS_PORT || nconf.get('redis:port'),
|
|
80
|
+
'redis'
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// allow a redis://user:host:port url, takes precedence
|
|
84
|
+
if (process.env.REDIS_URL) {
|
|
85
|
+
nconf.set('redis:url', process.env.REDIS_URL);
|
|
86
|
+
nconf.clear('redis:host');
|
|
87
|
+
nconf.clear('redis:port');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
get = (key: string): any => nconf.get(key);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const config = new Config();
|
|
94
|
+
export default config;
|
package/src/crypto.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import proxyquire from 'proxyquire';
|
|
3
|
+
|
|
4
|
+
const crypto = proxyquire('./crypto', {
|
|
5
|
+
'crypto': {
|
|
6
|
+
randomBytes: () => Buffer.alloc(16)
|
|
7
|
+
}
|
|
8
|
+
}).default;
|
|
9
|
+
|
|
10
|
+
const secret = 'a test secret.. that is 16 x 2..';
|
|
11
|
+
const data = {'foo': 'bar'};
|
|
12
|
+
const encryptedData = "00000000000000000000000000000000:0543ec94d863fbf4b7a19b48e69d9317";
|
|
13
|
+
|
|
14
|
+
describe('crypto', () => {
|
|
15
|
+
it('encrypts', () => {
|
|
16
|
+
expect(crypto.encrypt(data, secret)).to.be.equal(encryptedData);
|
|
17
|
+
});
|
|
18
|
+
it('decrypts', () => {
|
|
19
|
+
expect(crypto.decrypt(encryptedData, secret)).to.eql(data);
|
|
20
|
+
});
|
|
21
|
+
it('hashes', () => {
|
|
22
|
+
expect(crypto.hash('foobar')).to.be.equal('8843d7f');
|
|
23
|
+
});
|
|
24
|
+
it('randTokens 8', () => {
|
|
25
|
+
const token = crypto.randToken(8);
|
|
26
|
+
expect(token.length).to.be.equal(8);
|
|
27
|
+
});
|
|
28
|
+
it('randTokens 16', () => {
|
|
29
|
+
const token = crypto.randToken(16);
|
|
30
|
+
expect(token.length).to.be.equal(16);
|
|
31
|
+
});
|
|
32
|
+
it('randTokens 32', () => {
|
|
33
|
+
const token = crypto.randToken(32);
|
|
34
|
+
expect(token.length).to.be.equal(32);
|
|
35
|
+
});
|
|
36
|
+
it('randTokens 33+ will fail', () => {
|
|
37
|
+
expect(() => {
|
|
38
|
+
crypto.randToken(33);
|
|
39
|
+
}).to.throw();
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/crypto.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { randomBytes, createCipheriv, createDecipheriv, createHash } from 'crypto';
|
|
2
|
+
import { IActivityStream } from "@sockethub/schemas";
|
|
3
|
+
|
|
4
|
+
const ALGORITHM = 'aes-256-cbc',
|
|
5
|
+
IV_LENGTH = 16; // For AES, this is always 16
|
|
6
|
+
|
|
7
|
+
class Crypto {
|
|
8
|
+
constructor() {}
|
|
9
|
+
encrypt(json: IActivityStream, secret: string): string {
|
|
10
|
+
const iv = randomBytes(IV_LENGTH);
|
|
11
|
+
const cipher = createCipheriv(ALGORITHM, Buffer.from(secret), iv);
|
|
12
|
+
let encrypted = cipher.update(JSON.stringify(json));
|
|
13
|
+
|
|
14
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
15
|
+
return iv.toString('hex') + ':' + encrypted.toString('hex');
|
|
16
|
+
}
|
|
17
|
+
decrypt(text: string, secret: string): IActivityStream {
|
|
18
|
+
let parts = text.split(':');
|
|
19
|
+
const iv = Buffer.from(parts.shift(), 'hex');
|
|
20
|
+
const encryptedText = Buffer.from(parts.join(':'), 'hex');
|
|
21
|
+
const decipher = createDecipheriv(ALGORITHM, Buffer.from(secret), iv);
|
|
22
|
+
let decrypted = decipher.update(encryptedText);
|
|
23
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
24
|
+
return JSON.parse(decrypted.toString());
|
|
25
|
+
}
|
|
26
|
+
hash(text: string): string {
|
|
27
|
+
const shasum = createHash('sha1');
|
|
28
|
+
shasum.update(text);
|
|
29
|
+
return shasum.digest('hex').substring(0, 7);
|
|
30
|
+
}
|
|
31
|
+
randToken(len: number): string {
|
|
32
|
+
if (len > 32) {
|
|
33
|
+
throw new Error(`crypto.randToken supports a length param of up to 32, ${len} given`);
|
|
34
|
+
}
|
|
35
|
+
const buf = randomBytes(len);
|
|
36
|
+
return buf.toString('hex').substring(0, len);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const crypto = new Crypto();
|
|
41
|
+
export default crypto;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"activity-streams": {
|
|
3
|
+
"opts": {
|
|
4
|
+
"specialObjs": [ "credentials" ]
|
|
5
|
+
}
|
|
6
|
+
},
|
|
7
|
+
"examples": {
|
|
8
|
+
"enabled": false,
|
|
9
|
+
"secret": 1234567890
|
|
10
|
+
},
|
|
11
|
+
"sockethub": {
|
|
12
|
+
"port": 10550,
|
|
13
|
+
"host": "localhost",
|
|
14
|
+
"path": "/sockethub"
|
|
15
|
+
},
|
|
16
|
+
"log_file": "",
|
|
17
|
+
"platforms": [],
|
|
18
|
+
"public": {
|
|
19
|
+
"protocol": "http",
|
|
20
|
+
"host": "localhost",
|
|
21
|
+
"port": 10550,
|
|
22
|
+
"path": "/"
|
|
23
|
+
},
|
|
24
|
+
"redis": {
|
|
25
|
+
"host": "127.0.0.1",
|
|
26
|
+
"port": 6379
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const Sockethub = require('./sockethub').default;
|
|
2
|
+
const sockethub = new Sockethub();
|
|
3
|
+
|
|
4
|
+
module.exports = async () => {
|
|
5
|
+
process.once('uncaughtException', function (err) {
|
|
6
|
+
console.log('UNCAUGHT EXCEPTION');
|
|
7
|
+
// eslint-disable-next-line security-node/detect-crlf
|
|
8
|
+
console.log(err.stack);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
process.once('SIGTERM', function () {
|
|
13
|
+
console.log('Received TERM signal. Exiting.');
|
|
14
|
+
process.exit(0);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
process.once('SIGINT', function () {
|
|
18
|
+
console.log('Received INT signal. Exiting.');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
process.once('exit', async function () {
|
|
23
|
+
console.log('destroying all platform instances');
|
|
24
|
+
await sockethub.removeAllPlatformInstances();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
sockethub.boot();
|
|
28
|
+
};
|