Skip to content
This repository was archived by the owner on Jul 9, 2019. It is now read-only.

Commit fb4ca86

Browse files
committed
Bad test II
1 parent a0c9e69 commit fb4ca86

23 files changed

+318
-2
lines changed

__tests__/config.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
require("jest");
3+
describe("foo", function () {
4+
it("bars", function () {
5+
expect(true).toBe((true));
6+
});
7+
});

__tests__/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});

__tests__/logger.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});

__tests__/on_ready.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});

__tests__/security/authenticate.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"use strict";
2+
var verify_token_1 = require("../../app/security/verify_token");
3+
var fetch_real_token_1 = require("../../support/fetch_real_token");
4+
var EMAIL = "[email protected]";
5+
var PASSWORD = "password123";
6+
var validJWT;
7+
var invalidJWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbkBhZG1pbi5jb20iLCJpYXQiOjE0NTg4MTk1MzYsImp0aSI6ImE0MWQxMGU1LTk3NDUtNDEzOS1hYmJlLWQ5MjgzY2M2MGRjMiIsImlzcyI6ImZhcm1ib3Qtd2ViLWFwcCIsImV4cCI6MTQ1OTE2NTEzNiwiYWxnIjoiUlMyNTYifQ.reuRxMr_WMgu9prisSjGBuIuKRQw9Tmc5U_kWJyzFm0';
8+
describe("token verification", function () {
9+
beforeAll(function (done) {
10+
fetch_real_token_1.fetchRealJWT()
11+
.then(function (token) {
12+
validJWT = token;
13+
done();
14+
});
15+
});
16+
it("knows when you're lying", function (done) {
17+
function assertions(error) {
18+
expect(error.message).toBeDefined();
19+
done();
20+
}
21+
verify_token_1.verifyToken(invalidJWT).then(assertions, assertions);
22+
});
23+
it("knows when you're telling the truth", function (done) {
24+
function assertions(data) {
25+
expect(data.sub).toEqual('[email protected]');
26+
expect(data.iss).toEqual('//localhost:3000');
27+
done();
28+
}
29+
function failure(error) {
30+
fail("Failed to validate JWT. Error is above.");
31+
done();
32+
}
33+
verify_token_1.verifyToken(validJWT).then(assertions, failure);
34+
});
35+
});

__tests__/security/authenticate.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { authenticate as auth } from "../../app/security/authenticate";
1+
import { authenticate as auth } from "../../app/authentication/authenticate";
22
import { verifyToken as verify } from '../../app/security/verify_token';
33
import { fetchRealJWT } from "../../support/fetch_real_token";
44

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});

__tests__/security/can_use_topic.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
describe("foo", function () {
3+
it("bars", function () {
4+
expect(true).toBe((true));
5+
});
6+
});

__tests__/security/verify_token.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"use strict";
2+
var verify_token_1 = require("../../app/security/verify_token");
3+
var fetch_real_token_1 = require("../../support/fetch_real_token");
4+
var EMAIL = "[email protected]";
5+
var PASSWORD = "password123";
6+
var validJWT;
7+
var invalidJWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbkBhZG1pbi5jb20iLCJpYXQiOjE0NTg4MTk1MzYsImp0aSI6ImE0MWQxMGU1LTk3NDUtNDEzOS1hYmJlLWQ5MjgzY2M2MGRjMiIsImlzcyI6ImZhcm1ib3Qtd2ViLWFwcCIsImV4cCI6MTQ1OTE2NTEzNiwiYWxnIjoiUlMyNTYifQ.reuRxMr_WMgu9prisSjGBuIuKRQw9Tmc5U_kWJyzFm0';
8+
describe("token verification", function () {
9+
beforeAll(function (done) {
10+
fetch_real_token_1.fetchRealJWT()
11+
.then(function (token) {
12+
validJWT = token;
13+
done();
14+
});
15+
});
16+
it("knows when you're lying", function (done) {
17+
function assertions(error) {
18+
expect(error.message).toBeDefined();
19+
done();
20+
}
21+
verify_token_1.verifyToken(invalidJWT).then(assertions, assertions);
22+
});
23+
it("knows when you're telling the truth", function (done) {
24+
function assertions(data) {
25+
expect(data.sub).toEqual('[email protected]');
26+
expect(data.iss).toEqual('//localhost:3000');
27+
done();
28+
}
29+
function failure(error) {
30+
fail("Failed to validate JWT. Error is above.");
31+
done();
32+
}
33+
verify_token_1.verifyToken(validJWT).then(assertions, failure);
34+
});
35+
});

__tests__/security/verify_token.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { authenticate as auth } from "../../app/security/authenticate";
1+
import { authenticate as auth } from "../../app/authentication/authenticate";
22
import { verifyToken as verify } from '../../app/security/verify_token';
33
import { fetchRealJWT } from "../../support/fetch_real_token";
44

app/authentication/authenticate.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use strict";
2+
// test@test.com password123
3+
var verify_token_1 = require("../security/verify_token");
4+
var logger_1 = require("../logger");
5+
var authenticate_ok_1 = require("./authenticate_ok");
6+
var authenticate_no_1 = require("./authenticate_no");
7+
/** Determine if user is authorized to use the server. */
8+
function authenticate(client, username, password, callback) {
9+
logger_1.log("AUTH START");
10+
var ok = authenticate_ok_1.authenticateOk(client, callback, username);
11+
var no = authenticate_no_1.authenticateNo(client, callback, username);
12+
if (username && password) {
13+
verify_token_1.verifyToken(password.toString()).then(ok, no);
14+
}
15+
else {
16+
no(new Error("username and password required"));
17+
}
18+
}
19+
exports.authenticate = authenticate;

app/authentication/authenticate_no.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use strict";
2+
var logger_1 = require("../logger");
3+
/** Creates a function that is triggered when a JWT is invalid. */
4+
function authenticateNo(client, callback, username) {
5+
return function (error) {
6+
logger_1.log("AUTH FAIL " + username);
7+
logger_1.log(error.message);
8+
logger_1.log(error);
9+
client.authError = error;
10+
callback(null, false);
11+
};
12+
}
13+
exports.authenticateNo = authenticateNo;

app/authentication/authenticate_ok.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"use strict";
2+
var logger_1 = require("../logger");
3+
/** Creates a function that is triggered when a JWT is invalid. */
4+
function authenticateOk(client, callback, username) {
5+
return function (permissions) {
6+
logger_1.log("AUTH OK " + username);
7+
client.permissions = permissions;
8+
callback(null, true);
9+
};
10+
}
11+
exports.authenticateOk = authenticateOk;
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
var can_use_topic_1 = require("./can_use_topic");
3+
/** Determines if a user is allowed to publish to a particular topic. */
4+
function authorizePublish(client, topic, payload, callback) {
5+
callback(null, can_use_topic_1.canUseTopic(client, topic));
6+
}
7+
exports.authorizePublish = authorizePublish;
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
var can_use_topic_1 = require("./can_use_topic");
3+
/** Determines if a user is allowed to listen to a particular topic. */
4+
function authorizeSubscribe(client, topic, callback) {
5+
callback(null, can_use_topic_1.canUseTopic(client, topic));
6+
}
7+
exports.authorizeSubscribe = authorizeSubscribe;

app/authorization/can_use_topic.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use strict";
2+
var logger_1 = require("../logger");
3+
/** If a user has a bot of id XYZ, then they may access any topic
4+
* following pattern bot/XYZ/# */
5+
function canUseTopic(client, topic) {
6+
var hasBot = topic &&
7+
client &&
8+
client.permissions &&
9+
client.permissions.bot;
10+
if (!hasBot) {
11+
logger_1.log("Tried to access topic " +
12+
(topic || "???") +
13+
" but no bot/topic provided.");
14+
return false;
15+
}
16+
;
17+
var botID = client.permissions.bot;
18+
var allowedTopic = "bot/" + botID + "/";
19+
return topic.startsWith(allowedTopic);
20+
}
21+
exports.canUseTopic = canUseTopic;

app/config.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"use strict";
2+
var logger_1 = require("./logger");
3+
exports.webAppUrl = process.env.WEB_API_URL || "http://localhost:3000";
4+
logger_1.log("Using " + exports.webAppUrl + " as API URL");
5+
function generateConfig(sslDomain) {
6+
if (sslDomain === void 0) { sslDomain = ""; }
7+
var SSL_DIR = "/etc/letsencrypt/live/" + sslDomain + "/";
8+
var config = {
9+
allowNonSecure: true,
10+
port: 1883,
11+
http: {
12+
port: 3002,
13+
bundle: true,
14+
static: "./public"
15+
},
16+
https: {
17+
port: 443
18+
},
19+
secure: {
20+
port: 8883,
21+
keyPath: SSL_DIR + "privkey.pem",
22+
certPath: SSL_DIR + "cert.pem"
23+
}
24+
};
25+
// Remove SSL features if SSL_DOMAIN
26+
// was not set.
27+
if (!sslDomain) {
28+
delete config.https;
29+
delete config.secure;
30+
}
31+
return config;
32+
}
33+
exports.generateConfig = generateConfig;

app/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
var mosca_1 = require("mosca");
3+
var config_1 = require("./config");
4+
var on_ready_1 = require("./on_ready");
5+
var server = new mosca_1.Server(config_1.generateConfig(process.env.SSL_DOMAIN));
6+
server.on("ready", on_ready_1.onReady(server));

app/logger.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
function log(args) {
3+
if (!process.env.DISABLE_LOGS) {
4+
console.log.apply(this, arguments);
5+
}
6+
}
7+
exports.log = log;

app/on_ready.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use strict";
2+
var authenticate_1 = require("./authentication/authenticate");
3+
var authorize_publish_1 = require("./authorization/authorize_publish");
4+
var authorize_subscribe_1 = require("./authorization/authorize_subscribe");
5+
var logger_1 = require("./logger");
6+
exports.onReady = function (server) { return function () {
7+
logger_1.log("Server online");
8+
server.on("clientConnected", function () { return logger_1.log("clientConnected"); });
9+
server.on("clientDisconnecting", function () { return logger_1.log("clientDisconnecting"); });
10+
server.on("clientDisconnected", function () { return logger_1.log("clientDisconnected"); });
11+
server.on("published", function () {
12+
logger_1.log("\n=== Incoming Message ===");
13+
var output;
14+
try {
15+
console.log(arguments[0].topic);
16+
var s = String.fromCharCode.apply(null, new Uint16Array(arguments[0].payload));
17+
output = JSON.stringify(JSON.parse(s), null, 2);
18+
}
19+
catch (error) {
20+
output = arguments[0].payload;
21+
}
22+
finally {
23+
console.log(output);
24+
}
25+
});
26+
server.on("subscribed", function () { return logger_1.log("subscribed"); });
27+
server.on("unsubscribed", function () { return logger_1.log("unsubscribed"); });
28+
server.on("error", function () { return logger_1.log("error"); });
29+
server.authenticate = authenticate_1.authenticate;
30+
server.authorizePublish = authorize_publish_1.authorizePublish;
31+
server.authorizeSubscribe = authorize_subscribe_1.authorizeSubscribe;
32+
}; };

app/security/verify_token.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use strict";
2+
var config_1 = require("../config");
3+
var axios_1 = require("axios");
4+
var jwt = require("jsonwebtoken");
5+
var logger_1 = require("../logger");
6+
var url = config_1.webAppUrl + "/api/public_key";
7+
function keyOk(resp) {
8+
logger_1.log("Downloaded certificate from " + url);
9+
return new Buffer(resp.data, "utf8");
10+
}
11+
function no(error) {
12+
logger_1.log("Unable to download certificate from " + url);
13+
logger_1.log("Is the FarmBot API running?");
14+
process.exit();
15+
}
16+
var getCertificate = axios_1.default.get(url).then(keyOk, no);
17+
function verifyToken(token) {
18+
function no(error) {
19+
logger_1.log("Unable to verify token " + url);
20+
}
21+
function ok(cert) {
22+
logger_1.log("Did fetch certificate. Will verify token with certificate.");
23+
return jwt.verify(token, cert, { algorithms: ["RS256"] });
24+
}
25+
logger_1.log("Will fetch certificate...");
26+
return getCertificate.then(ok, no);
27+
}
28+
exports.verifyToken = verifyToken;
29+
;

support/fetch_real_token.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"use strict";
2+
var axios_1 = require("axios");
3+
var p = axios_1.default.post("http://localhost:3000/api/tokens", {
4+
user: {
5+
6+
password: "password123"
7+
}
8+
});
9+
function fetchRealJWT() {
10+
function ok(resp) {
11+
return resp.data.token.encoded;
12+
}
13+
function no() {
14+
console.log("\n We test the MQTT server against a real running API instance on localhost:3000.\n Something went wrong while testing.\n Usually, this means you are not running a server.\n ");
15+
}
16+
return p.then(ok, no);
17+
}
18+
exports.fetchRealJWT = fetchRealJWT;

0 commit comments

Comments
 (0)