🔀 Merge dev to auth branch
This commit is contained in:
@@ -141,6 +141,7 @@ const migrateAppConfigs = (config: BackendConfigType) => {
|
||||
...app.appearance,
|
||||
appNameStatus: app.appearance.appNameStatus?? 'normal',
|
||||
positionAppName: app.appearance.positionAppName?? 'column',
|
||||
appNameFontSize: app.appearance.appNameFontSize?? 16,
|
||||
lineClampAppName: app.appearance.lineClampAppName?? 1,
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import Consola from 'consola';
|
||||
import { z } from 'zod';
|
||||
import { trimStringEnding } from '~/tools/shared/strings';
|
||||
import {
|
||||
@@ -60,19 +62,41 @@ export class AdGuard {
|
||||
await this.changeProtectionStatus(false);
|
||||
}
|
||||
async enable() {
|
||||
await this.changeProtectionStatus(false);
|
||||
await this.changeProtectionStatus(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a post request to the AdGuard API to change the protection status based on the value of newStatus
|
||||
* @param {boolean} newStatus - The new status of the protection
|
||||
* @param {number} duration - Duration of a pause, in milliseconds. Enabled should be false.
|
||||
* @returns {string} - The response from the AdGuard API
|
||||
*/
|
||||
private async changeProtectionStatus(newStatus: boolean, duration = 0) {
|
||||
await fetch(`${this.baseHostName}/control/protection`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
enabled: newStatus,
|
||||
duration,
|
||||
}),
|
||||
});
|
||||
try {
|
||||
const { data }: { data: string } = await axios.post(
|
||||
`${this.baseHostName}/control/protection`,
|
||||
{
|
||||
enabled: newStatus,
|
||||
duration,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Basic ${this.getAuthorizationHeaderValue()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
Consola.error(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It return a base64 username:password string
|
||||
* @returns {string} The base64 encoded username and password
|
||||
*/
|
||||
private getAuthorizationHeaderValue() {
|
||||
return Buffer.from(`${this.username}:${this.password}`).toString('base64');
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ describe('PiHole API client', () => {
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') {
|
||||
@@ -170,6 +171,13 @@ describe('PiHole API client', () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){
|
||||
countTriedRequests += 1;
|
||||
return JSON.stringify({
|
||||
status: 'enabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
@@ -181,6 +189,7 @@ describe('PiHole API client', () => {
|
||||
// Assert
|
||||
expect(summary).toBe(true);
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).toBe(1);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
@@ -188,12 +197,13 @@ describe('PiHole API client', () => {
|
||||
errorLogSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('enable - return false when state change is not as expected', async () => {
|
||||
it('enable - return true when state change is as expected after 10 retries', async () => {
|
||||
// arrange
|
||||
const errorLogSpy = vi.spyOn(Consola, 'error');
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') {
|
||||
@@ -203,6 +213,19 @@ describe('PiHole API client', () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){
|
||||
countTriedRequests += 1;
|
||||
if(countTriedRequests < 10) {
|
||||
return JSON.stringify({
|
||||
status: 'disabled',
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
status: 'enabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
@@ -212,8 +235,9 @@ describe('PiHole API client', () => {
|
||||
const summary = await client.enable();
|
||||
|
||||
// Assert
|
||||
expect(summary).toBe(false);
|
||||
expect(summary).toBe(true);
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).toBe(10);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
@@ -227,6 +251,7 @@ describe('PiHole API client', () => {
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') {
|
||||
@@ -236,6 +261,13 @@ describe('PiHole API client', () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){
|
||||
countTriedRequests += 1;
|
||||
return JSON.stringify({
|
||||
status: 'disabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
@@ -247,6 +279,7 @@ describe('PiHole API client', () => {
|
||||
// Assert
|
||||
expect(summary).toBe(true);
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).toBe(1);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
@@ -254,12 +287,13 @@ describe('PiHole API client', () => {
|
||||
errorLogSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('disable - return false when state change is not as expected', async () => {
|
||||
it('disable - return true when state change is as expected after 10 retries', async () => {
|
||||
// arrange
|
||||
const errorLogSpy = vi.spyOn(Consola, 'error');
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') {
|
||||
@@ -269,6 +303,19 @@ describe('PiHole API client', () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){
|
||||
countTriedRequests += 1;
|
||||
if(countTriedRequests < 10) {
|
||||
return JSON.stringify({
|
||||
status: 'enabled',
|
||||
});
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
status: 'disabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
@@ -278,8 +325,95 @@ describe('PiHole API client', () => {
|
||||
const summary = await client.disable();
|
||||
|
||||
// Assert
|
||||
expect(summary).toBe(false);
|
||||
expect(summary).toBe(true);
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).toBe(10);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
|
||||
errorLogSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('enable - throw error when state change is not as expected', async () => {
|
||||
// arrange
|
||||
const errorLogSpy = vi.spyOn(Consola, 'error');
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') {
|
||||
calledCount += 1;
|
||||
return JSON.stringify({
|
||||
status: 'disabled',
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){
|
||||
countTriedRequests += 1;
|
||||
return JSON.stringify({
|
||||
status: 'disabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
const client = new PiHoleClient('http://pi.hole', 'nice');
|
||||
|
||||
// Act & Assert
|
||||
await expect(() => client.enable()).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Although PiHole received the command, it failed to update it\'s status: [object Object]"'
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).toBe(10);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
|
||||
errorLogSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('disable - throw error when state change is not as expected', async () => {
|
||||
// arrange
|
||||
const errorLogSpy = vi.spyOn(Consola, 'error');
|
||||
const warningLogSpy = vi.spyOn(Consola, 'warn');
|
||||
|
||||
let calledCount = 0;
|
||||
let countTriedRequests = 0;
|
||||
|
||||
fetchMock.mockResponse((request) => {
|
||||
if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') {
|
||||
calledCount += 1;
|
||||
return JSON.stringify({
|
||||
status: 'enabled',
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice') {
|
||||
countTriedRequests += 1;
|
||||
return JSON.stringify({
|
||||
status: 'enabled',
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Bad url: ${request.url}`));
|
||||
});
|
||||
|
||||
const client = new PiHoleClient('http://pi.hole', 'nice');
|
||||
|
||||
// Act & Assert
|
||||
await expect(() => client.disable()).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Although PiHole received the command, it failed to update it\'s status: [object Object]"'
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(calledCount).toBe(1);
|
||||
expect(countTriedRequests).lessThanOrEqual(10);
|
||||
|
||||
expect(errorLogSpy).not.toHaveBeenCalled();
|
||||
expect(warningLogSpy).not.toHaveBeenCalled();
|
||||
|
||||
@@ -62,6 +62,18 @@ export class PiHoleClient {
|
||||
);
|
||||
}
|
||||
|
||||
return json as PiHoleApiStatusChangeResponse;
|
||||
for(let loops = 0; loops < 10; loops++){
|
||||
const summary = await this.getSummary()
|
||||
if (summary.status === action + 'd'){
|
||||
return { status: summary.status } as PiHoleApiStatusChangeResponse;
|
||||
}
|
||||
await new Promise ((resolve) => { setTimeout(resolve, 50)});
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
`Although PiHole received the command, it failed to update it's status: ${json}`
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ export const boardNamespaces = [
|
||||
'layout/mobile/drawer',
|
||||
'settings/common',
|
||||
'settings/general/config-changer',
|
||||
'settings/general/edit-mode-toggle',
|
||||
'settings/general/internationalization',
|
||||
'settings/general/search-engine',
|
||||
'settings/general/theme-selector',
|
||||
'settings/general/widget-positions',
|
||||
'modules/common',
|
||||
'modules/date',
|
||||
|
||||
Reference in New Issue
Block a user