Skip to content

Commit

Permalink
Refactor Host to class & add default path
Browse files Browse the repository at this point in the history
  • Loading branch information
cbundy authored and mattwebbio committed Nov 6, 2022
1 parent ae1ef6a commit cc1237e
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 115 deletions.
101 changes: 49 additions & 52 deletions src/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,23 @@ import { jest } from '@jest/globals';
import nock from 'nock';
import { Blob } from 'node-fetch';
import { Client } from './client';
import type { Host } from './config';
import { Host } from './config';
import { Config } from './config';
import { ErrorNotification } from './notify';

describe('Client', () => {
const host: Host = {
baseUrl: 'http://10.0.0.2',
password: 'mypassword'
};
const host = new Host('http://10.0.0.2', 'mypassword');

const createClient = async () => {
nock(host.baseUrl).get('/admin/index.php?login').reply(200);
nock(host.baseUrl)
nock(host.fullUrl).get('/admin/index.php?login').reply(200);
nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(
200,
'<html><body><div id="token">abcdefgijklmnopqrstuvwxyzabcdefgijklmnopqrst</div></body></html>'
);

return { teleporter: nock(host.baseUrl), client: await Client.create(host) };
return { teleporter: nock(host.fullUrl), client: await Client.create(host) };
};

beforeEach(() => {
Expand All @@ -30,8 +27,8 @@ describe('Client', () => {

describe('create', () => {
test('should throw error if status code is not ok', async () => {
const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.baseUrl).post('/admin/index.php?login').reply(500);
const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.fullUrl).post('/admin/index.php?login').reply(500);

const expectError = expect(Client.create(host)).rejects;

Expand All @@ -50,8 +47,8 @@ describe('Client', () => {
});

test('should throw error if no token is present', async () => {
const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.baseUrl).post('/admin/index.php?login').reply(200);
const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.fullUrl).post('/admin/index.php?login').reply(200);

const expectError = expect(Client.create(host)).rejects;

Expand All @@ -69,8 +66,8 @@ describe('Client', () => {
});

test('should throw error if token is in incorrect format', async () => {
const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.baseUrl)
const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(200, '<html><body><div id="token">abcdef</div></body></html>');

Expand All @@ -90,8 +87,8 @@ describe('Client', () => {
});

test('should return client', async () => {
const initialRequest = nock(host.baseUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.baseUrl)
const initialRequest = nock(host.fullUrl).get('/admin/index.php?login').reply(200);
const loginRequest = nock(host.fullUrl)
.post('/admin/index.php?login')
.reply(
200,
Expand Down Expand Up @@ -237,18 +234,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)<br>\n' +
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
);
teleporter
.get('/admin/scripts/pi-hole/php/gravity.sh.php', undefined)
Expand Down Expand Up @@ -276,18 +273,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)<br>\n' +
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
);
teleporter
.get('/admin/scripts/pi-hole/php/gravity.sh.php', undefined)
Expand Down Expand Up @@ -336,18 +333,18 @@ describe('Client', () => {
.reply(
200,
'Processed adlist (14 entries)<br>\n' +
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
'Processed adlist group assignments (13 entries)<br>\n' +
'Processed blacklist (exact) (0 entries)<br>\n' +
'Processed blacklist (regex) (3 entries)<br>\n' +
'Processed client (8 entries)<br>\n' +
'Processed client group assignments (16 entries)<br>\n' +
'Processed local DNS records (41 entries)<br>\n' +
'Processed domain_audit (0 entries)<br>\n' +
'Processed black-/whitelist group assignments (10 entries)<br>\n' +
'Processed group (3 entries)<br>\n' +
'Processed whitelist (exact) (4 entries)<br>\n' +
'Processed whitelist (regex) (0 entries)<br>\n' +
'OK'
);

const result = await client.uploadBackup(backup);
Expand Down
52 changes: 26 additions & 26 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ export class Client {
private fetch: NodeFetchCookie,
private host: Host,
private token: string
) {}
) { }

public static async create(host: Host): Promise<Client> {
Log.info(chalk.yellow(`➡️ Signing in to ${host.baseUrl}...`));
Log.info(chalk.yellow(`➡️ Signing in to ${host.fullUrl}...`));
const fetch = fetchCookie(nodeFetch);

await fetch(`${host.baseUrl}/admin/index.php?login`, { method: 'GET' });
const response = await fetch(`${host.baseUrl}/admin/index.php?login`, {
await fetch(`${host.fullUrl}/admin/index.php?login`, { method: 'GET' });
const response = await fetch(`${host.fullUrl}/admin/index.php?login`, {
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
Expand All @@ -34,17 +34,17 @@ export class Client {
});
if (response.status !== 200)
throw new ErrorNotification({
message: `There was an error logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
message: `There was an error logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
host: host.baseUrl,
host: host.fullUrl,
status: response.status,
responseBody: await response.text()
}
});

const token = this.parseResponseForToken(host, await response.text());

Log.info(chalk.green(`✔️ Successfully signed in to ${host.baseUrl}!`));
Log.info(chalk.green(`✔️ Successfully signed in to ${host.fullUrl}!`));
return new this(fetch, host, token);
}

Expand All @@ -53,19 +53,19 @@ export class Client {
const tokenDiv = root.querySelector('#token');
if (!tokenDiv)
throw new ErrorNotification({
message: `No token could be found while logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
message: `No token could be found while logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
host: host.baseUrl,
host: host.fullUrl,
innerHtml: root.innerHTML
}
});

const token = tokenDiv.innerText;
if (token.length != 44)
throw new ErrorNotification({
message: `A token was found but could not be validated while logging in to "${host.baseUrl}" - are you able to log in with the configured password?`,
message: `A token was found but could not be validated while logging in to "${host.fullUrl}" - are you able to log in with the configured password?`,
verbose: {
host: host.baseUrl,
host: host.fullUrl,
token: token
}
});
Expand All @@ -74,11 +74,11 @@ export class Client {
}

public async downloadBackup(): Promise<Blob> {
Log.info(chalk.yellow(`➡️ Downloading backup from ${this.host.baseUrl}...`));
Log.info(chalk.yellow(`➡️ Downloading backup from ${this.host.fullUrl}...`));
const form = this.generateForm();

const response = await this.fetch(
`${this.host.baseUrl}/admin/scripts/pi-hole/php/teleporter.php`,
`${this.host.fullUrl}/admin/scripts/pi-hole/php/teleporter.php`,
{
body: form,
method: 'POST'
Expand All @@ -89,29 +89,29 @@ export class Client {
response.headers.get('content-type') !== 'application/gzip'
)
throw new ErrorNotification({
message: `Failed to download backup from "${this.host.baseUrl}".`,
message: `Failed to download backup from "${this.host.fullUrl}".`,
verbose: {
host: this.host.baseUrl,
host: this.host.fullUrl,
status: response.status,
responseBody: await response.text()
}
});

const data = await response.arrayBuffer();

Log.info(chalk.green(`✔️ Backup from ${this.host.baseUrl} completed!`));
Log.info(chalk.green(`✔️ Backup from ${this.host.fullUrl} completed!`));
return new Blob([data]);
}

public async uploadBackup(backup: Blob): Promise<true | never> {
Log.info(chalk.yellow(`➡️ Uploading backup to ${this.host.baseUrl}...`));
Log.info(chalk.yellow(`➡️ Uploading backup to ${this.host.fullUrl}...`));

const form = this.generateForm();
form.append('action', 'in');
form.append('zip_file', backup, 'backup.tar.gz');

const uploadResponse = await this.fetch(
`${this.host.baseUrl}/admin/scripts/pi-hole/php/teleporter.php`,
`${this.host.fullUrl}/admin/scripts/pi-hole/php/teleporter.php`,
{
body: form,
method: 'POST'
Expand All @@ -120,21 +120,21 @@ export class Client {
const uploadText = await uploadResponse.text();
if (uploadResponse.status !== 200 || !uploadText.endsWith('OK'))
throw new ErrorNotification({
message: `Failed to upload backup to "${this.host.baseUrl}".`,
message: `Failed to upload backup to "${this.host.fullUrl}".`,
verbose: {
host: this.host.baseUrl,
host: this.host.fullUrl,
status: uploadResponse.status,
responseBody: uploadText
}
});

Log.info(chalk.green(`✔️ Backup uploaded to ${this.host.baseUrl}!`));
Log.info(chalk.green(`✔️ Backup uploaded to ${this.host.fullUrl}!`));
Log.verbose(`Result:\n${chalk.blue(uploadText)}`);

if (Config.updateGravity) {
Log.info(chalk.yellow(`➡️ Updating gravity on ${this.host.baseUrl}...`));
Log.info(chalk.yellow(`➡️ Updating gravity on ${this.host.fullUrl}...`));
const gravityUpdateResponse = await this.fetch(
`${this.host.baseUrl}/admin/scripts/pi-hole/php/gravity.sh.php`,
`${this.host.fullUrl}/admin/scripts/pi-hole/php/gravity.sh.php`,
{ method: 'GET' }
);

Expand All @@ -146,15 +146,15 @@ export class Client {
!updateText.endsWith('Pi-hole blocking is enabled')
)
throw new ErrorNotification({
message: `Failed updating gravity on "${this.host.baseUrl}".`,
message: `Failed updating gravity on "${this.host.fullUrl}".`,
verbose: {
host: this.host.baseUrl,
host: this.host.fullUrl,
status: gravityUpdateResponse.status,
eventStream: updateText
}
});

Log.info(chalk.green(`✔️ Gravity updated on ${this.host.baseUrl}!`));
Log.info(chalk.green(`✔️ Gravity updated on ${this.host.fullUrl}!`));
Log.verbose(`Result:\n${chalk.blue(updateText)}`);
}

Expand Down
28 changes: 19 additions & 9 deletions src/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ describe('Config', () => {

const expected = {
baseUrl: 'http://10.0.0.2',
fullUrl: 'http://10.0.0.2',
path: '',
password: 'mypassword'
};

expect(Config.primaryHost).toStrictEqual(expected);
expect(Config.primaryHost).toEqual(expected);
resetEnv();
expect(Config.primaryHost).toStrictEqual(expected);
expect(Config.primaryHost).toEqual(expected);
});
});

Expand Down Expand Up @@ -132,13 +134,15 @@ describe('Config', () => {
const expected = [
{
baseUrl: 'http://10.0.0.3',
password: 'mypassword'
password: 'mypassword',
fullUrl: 'http://10.0.0.3',
path: ''
}
];

expect(Config.secondaryHosts).toStrictEqual(expected);
expect(Config.secondaryHosts).toEqual(expected);
resetEnv();
expect(Config.secondaryHosts).toStrictEqual(expected);
expect(Config.secondaryHosts).toEqual(expected);
});

test('should return multiple secondary hosts', () => {
Expand All @@ -151,18 +155,24 @@ describe('Config', () => {
process.env['SECONDARY_HOST_5_BASE_URL'] = 'http://10.0.0.7';
process.env['SECONDARY_HOST_5_PASSWORD'] = 'mypassword4';

expect(Config.secondaryHosts).toStrictEqual([
expect(Config.secondaryHosts).toEqual([
{
baseUrl: 'http://10.0.0.3',
password: 'mypassword1'
password: 'mypassword1',
fullUrl: 'http://10.0.0.3',
path: ''
},
{
baseUrl: 'http://10.0.0.4',
password: 'mypassword2'
password: 'mypassword2',
fullUrl: 'http://10.0.0.4',
path: ''
},
{
baseUrl: 'http://10.0.0.5',
password: 'mypassword3'
password: 'mypassword3',
fullUrl: 'http://10.0.0.5',
path: ''
}
]);
});
Expand Down
Loading

0 comments on commit cc1237e

Please sign in to comment.