Merge pull request #1546 from SkynetLabs/auth-only-portal-health-check-user
support auth only portal mode in health-check module
This commit is contained in:
commit
12b6a5f407
|
@ -1,7 +1,7 @@
|
||||||
const got = require("got");
|
const got = require("got");
|
||||||
const FormData = require("form-data");
|
const FormData = require("form-data");
|
||||||
const { isEqual } = require("lodash");
|
const { isEqual } = require("lodash");
|
||||||
const { calculateElapsedTime, getResponseContent } = require("../utils");
|
const { calculateElapsedTime, getResponseContent, getAuthCookie } = require("../utils");
|
||||||
const { SkynetClient, stringToUint8ArrayUtf8, genKeyPairAndSeed } = require("skynet-js");
|
const { SkynetClient, stringToUint8ArrayUtf8, genKeyPairAndSeed } = require("skynet-js");
|
||||||
|
|
||||||
const skynetClient = new SkynetClient(process.env.SKYNET_PORTAL_API);
|
const skynetClient = new SkynetClient(process.env.SKYNET_PORTAL_API);
|
||||||
|
@ -34,6 +34,7 @@ async function skydConfigCheck(done) {
|
||||||
|
|
||||||
// uploadCheck returns the result of uploading a sample file
|
// uploadCheck returns the result of uploading a sample file
|
||||||
async function uploadCheck(done) {
|
async function uploadCheck(done) {
|
||||||
|
const authCookie = await getAuthCookie();
|
||||||
const time = process.hrtime();
|
const time = process.hrtime();
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
const payload = Buffer.from(new Date()); // current date to ensure data uniqueness
|
const payload = Buffer.from(new Date()); // current date to ensure data uniqueness
|
||||||
|
@ -42,7 +43,10 @@ async function uploadCheck(done) {
|
||||||
form.append("file", payload, { filename: "time.txt", contentType: "text/plain" });
|
form.append("file", payload, { filename: "time.txt", contentType: "text/plain" });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await got.post(`${process.env.SKYNET_PORTAL_API}/skynet/skyfile`, { body: form });
|
const response = await got.post(`${process.env.SKYNET_PORTAL_API}/skynet/skyfile`, {
|
||||||
|
body: form,
|
||||||
|
headers: { cookie: authCookie },
|
||||||
|
});
|
||||||
|
|
||||||
data.statusCode = response.statusCode;
|
data.statusCode = response.statusCode;
|
||||||
data.up = true;
|
data.up = true;
|
||||||
|
@ -170,11 +174,12 @@ async function accountHealthCheck(done) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function genericAccessCheck(name, url) {
|
async function genericAccessCheck(name, url) {
|
||||||
|
const authCookie = await getAuthCookie();
|
||||||
const time = process.hrtime();
|
const time = process.hrtime();
|
||||||
const data = { up: false, url };
|
const data = { up: false, url };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await got(url, { headers: { cookie: "nocache=true" } });
|
const response = await got(url, { headers: { cookie: `nocache=true;${authCookie}` } });
|
||||||
|
|
||||||
data.statusCode = response.statusCode;
|
data.statusCode = response.statusCode;
|
||||||
data.up = true;
|
data.up = true;
|
||||||
|
|
|
@ -2,7 +2,7 @@ const got = require("got");
|
||||||
const hasha = require("hasha");
|
const hasha = require("hasha");
|
||||||
const { detailedDiff } = require("deep-object-diff");
|
const { detailedDiff } = require("deep-object-diff");
|
||||||
const { isEqual } = require("lodash");
|
const { isEqual } = require("lodash");
|
||||||
const { calculateElapsedTime, ensureValidJSON, getResponseContent } = require("../utils");
|
const { calculateElapsedTime, ensureValidJSON, getResponseContent, getAuthCookie } = require("../utils");
|
||||||
const { parseSkylink } = require("skynet-js");
|
const { parseSkylink } = require("skynet-js");
|
||||||
|
|
||||||
// audioExampleCheck returns the result of trying to download the skylink
|
// audioExampleCheck returns the result of trying to download the skylink
|
||||||
|
@ -1130,12 +1130,13 @@ function parseHeaderString(header) {
|
||||||
|
|
||||||
// skylinkVerification verifies a skylink against provided information.
|
// skylinkVerification verifies a skylink against provided information.
|
||||||
async function skylinkVerification(done, expected, { followRedirect = true, method = "get" } = {}) {
|
async function skylinkVerification(done, expected, { followRedirect = true, method = "get" } = {}) {
|
||||||
|
const authCookie = await getAuthCookie();
|
||||||
const time = process.hrtime();
|
const time = process.hrtime();
|
||||||
const details = { name: expected.name, skylink: expected.skylink };
|
const details = { name: expected.name, skylink: expected.skylink };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query = `${process.env.SKYNET_PORTAL_API}/${expected.skylink}`;
|
const query = `${process.env.SKYNET_PORTAL_API}/${expected.skylink}`;
|
||||||
const response = await got[method](query, { followRedirect, headers: { cookie: "nocache=true" } });
|
const response = await got[method](query, { followRedirect, headers: { cookie: `nocache=true;${authCookie}` } });
|
||||||
const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) };
|
const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) };
|
||||||
const info = {};
|
const info = {};
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,18 @@ if (!process.env.SKYNET_PORTAL_API) {
|
||||||
throw new Error("You need to provide SKYNET_PORTAL_API environment variable");
|
throw new Error("You need to provide SKYNET_PORTAL_API environment variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.ACCOUNTS_ENABLED === "true" && !process.env.SKYNET_DASHBOARD_URL) {
|
if (process.env.ACCOUNTS_ENABLED === "true") {
|
||||||
throw new Error("You need to provide SKYNET_DASHBOARD_URL environment variable when accounts are enabled");
|
if (!process.env.SKYNET_DASHBOARD_URL) {
|
||||||
|
throw new Error("You need to provide SKYNET_DASHBOARD_URL environment variable when accounts are enabled");
|
||||||
|
}
|
||||||
|
if (process.env.ACCOUNTS_LIMIT_ACCESS === "authenticated") {
|
||||||
|
if (!process.env.ACCOUNTS_TEST_USER_EMAIL) {
|
||||||
|
throw new Error("ACCOUNTS_TEST_USER_EMAIL cannot be empty");
|
||||||
|
}
|
||||||
|
if (!process.env.ACCOUNTS_TEST_USER_PASSWORD) {
|
||||||
|
throw new Error("ACCOUNTS_TEST_USER_PASSWORD cannot be empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const got = require("got");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time between start and now in milliseconds
|
* Get the time between start and now in milliseconds
|
||||||
*/
|
*/
|
||||||
|
@ -39,9 +41,69 @@ function ensureValidJSON(object) {
|
||||||
return JSON.parse(stringified);
|
return JSON.parse(stringified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate with given credentials and return auth cookie
|
||||||
|
* Creates new account if username does not exist
|
||||||
|
* Only authenticates when portal is set to authenticated users only mode
|
||||||
|
*/
|
||||||
|
function getAuthCookie() {
|
||||||
|
// cache auth promise so only one actual request will be made
|
||||||
|
if (getAuthCookie.cache) return getAuthCookie.cache;
|
||||||
|
|
||||||
|
// do not authenticate if it is not necessary
|
||||||
|
if (process.env.ACCOUNTS_LIMIT_ACCESS !== "authenticated") return {};
|
||||||
|
|
||||||
|
const email = process.env.ACCOUNTS_TEST_USER_EMAIL;
|
||||||
|
const password = process.env.ACCOUNTS_TEST_USER_PASSWORD;
|
||||||
|
|
||||||
|
if (!email) throw new Error("ACCOUNTS_TEST_USER_EMAIL cannot be empty");
|
||||||
|
if (!password) throw new Error("ACCOUNTS_TEST_USER_PASSWORD cannot be empty");
|
||||||
|
|
||||||
|
async function authenticate() {
|
||||||
|
try {
|
||||||
|
// authenticate with given test user credentials
|
||||||
|
const response = await got.post(`${process.env.SKYNET_DASHBOARD_URL}/api/login`, {
|
||||||
|
json: { email, password },
|
||||||
|
});
|
||||||
|
|
||||||
|
// extract set-cookie from successful authentication request
|
||||||
|
const cookies = response.headers["set-cookie"];
|
||||||
|
|
||||||
|
// throw meaningful error when set-cookie header is missing
|
||||||
|
if (!cookies) throw new Error(`Auth successful (code ${response.statusCode}) but 'set-cookie' header is missing`);
|
||||||
|
|
||||||
|
// find the skynet-jwt cookie
|
||||||
|
const jwtcookie = cookies.find((cookie) => cookie.startsWith("skynet-jwt"));
|
||||||
|
|
||||||
|
// throw meaningful error when skynet-jwt cookie is missing
|
||||||
|
if (!jwtcookie) throw new Error(`Header 'set-cookie' found but 'skynet-jwt' cookie is missing`);
|
||||||
|
|
||||||
|
// extract just the cookie value (no set-cookie props) from set-cookie
|
||||||
|
return jwtcookie.match(/skynet-jwt=[^;]+;/)[0];
|
||||||
|
} catch (error) {
|
||||||
|
// 401 means that service worked but user could not have been authenticated
|
||||||
|
if (error.response && error.response.statusCode === 401) {
|
||||||
|
// sign up with the given credentials
|
||||||
|
await got.post(`${process.env.SKYNET_DASHBOARD_URL}/api/user`, {
|
||||||
|
json: { email, password },
|
||||||
|
});
|
||||||
|
|
||||||
|
// retry authentication
|
||||||
|
return authenticate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// rethrow unhandled exception
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (getAuthCookie.cache = authenticate());
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
calculateElapsedTime,
|
calculateElapsedTime,
|
||||||
getYesterdayISOString,
|
getYesterdayISOString,
|
||||||
getResponseContent,
|
getResponseContent,
|
||||||
ensureValidJSON,
|
ensureValidJSON,
|
||||||
|
getAuthCookie,
|
||||||
};
|
};
|
||||||
|
|
Reference in New Issue