Improved input validation, added tests
This commit is contained in:
parent
cb9bfa4499
commit
e21b9895a7
4 changed files with 120 additions and 16 deletions
|
@ -42,9 +42,11 @@
|
|||
"nostrRelay": "Nostr Relay",
|
||||
"nostrZapNotify": "Nostr Zap Notifications",
|
||||
"useNostr": "Use Nostr datasource",
|
||||
"bitaxeHostname": "BitAxe hostname",
|
||||
"bitaxeHostname": "BitAxe hostname or IP",
|
||||
"bitaxeEnabled": "Enable BitAxe",
|
||||
"nostrZapPubkey": "Nostr Zap pubkey"
|
||||
"nostrZapPubkey": "Nostr Zap pubkey",
|
||||
"invalidNostrPubkey": "Invalid Nostr pubkey, note that your pubkey does NOT start with npub.",
|
||||
"convertingValidNpub": "Converting valid npub to pubkey"
|
||||
},
|
||||
"control": {
|
||||
"systemInfo": "System info",
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
<div class="">
|
||||
<Toast
|
||||
isOpen={toastIsOpen}
|
||||
class="me-1 bg-{toastColor}"
|
||||
class="me-1 bg-{toastColor} text-bg-{toastColor}"
|
||||
autohide
|
||||
on:close={() => (toastIsOpen = false)}
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { isValidNostrRelay, getPubKey, isValidHexPubKey } from '$lib';
|
||||
import { isValidNostrRelay, getPubKey, isValidHexPubKey, isValidNpub } from '$lib';
|
||||
import { PUBLIC_BASE_URL } from '$lib/config';
|
||||
import { uiSettings } from '$lib/uiSettings';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
@ -52,6 +52,10 @@
|
|||
|
||||
const onSave = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
|
||||
// const form = e.target as HTMLFormElement;
|
||||
// const formData = new FormData(form);
|
||||
|
||||
let formSettings = $settings;
|
||||
|
||||
delete formSettings['gitRev'];
|
||||
|
@ -84,8 +88,49 @@
|
|||
validNostrRelay = await isValidNostrRelay($settings.nostrRelay);
|
||||
};
|
||||
|
||||
const checkValidNostrPubkey = () => {
|
||||
$settings.nostrPubKey = getPubKey($settings.nostrPubKey);
|
||||
let validBitaxe = false;
|
||||
const testBitaxe = async () => {
|
||||
try {
|
||||
const response = await fetch(`http://${$settings.bitaxeHostname}/api/system/info`);
|
||||
|
||||
if (!response.ok) {
|
||||
dispatch('showToast', {
|
||||
color: 'danger',
|
||||
text: `Failed to connect to BitAxe HTTP error! status: ${response.status}`
|
||||
});
|
||||
validBitaxe = false;
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
const systemInfo = await response.json();
|
||||
dispatch('showToast', {
|
||||
color: 'success',
|
||||
text: `Connected to BitAxe ${systemInfo.ASICModel} (Board version ${systemInfo.boardVersion}) running firmware ${systemInfo.version}.\r\nCurrent hashrate ${Math.round(systemInfo.hashRate)} GH/s`
|
||||
});
|
||||
validBitaxe = true;
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError && error.message.includes('Failed to fetch')) {
|
||||
dispatch('showToast', {
|
||||
color: 'danger',
|
||||
text: `Failed to connect to BitAxe, make sure you are connected to the same network.`
|
||||
});
|
||||
}
|
||||
console.error('Failed to fetch Bitaxe system info:', error);
|
||||
validBitaxe = false;
|
||||
}
|
||||
};
|
||||
|
||||
const checkValidNostrPubkey = (key) => {
|
||||
if (isValidNpub($settings[key])) {
|
||||
dispatch('showToast', {
|
||||
color: 'info',
|
||||
text: $_('section.settings.convertingValidNpub')
|
||||
});
|
||||
}
|
||||
|
||||
let ret = getPubKey($settings[key]);
|
||||
|
||||
if (ret) $settings[key] = ret;
|
||||
};
|
||||
|
||||
const onFlBrightnessChange = async () => {
|
||||
|
@ -160,6 +205,7 @@
|
|||
id="timePerScreen"
|
||||
min={1}
|
||||
step="1"
|
||||
required
|
||||
bind:value={$settings.timePerScreen}
|
||||
/>
|
||||
<InputGroupText>{$_('time.minutes')}</InputGroupText>
|
||||
|
@ -177,6 +223,7 @@
|
|||
id="fullRefreshMin"
|
||||
min={1}
|
||||
step="1"
|
||||
required
|
||||
bind:value={$settings.fullRefreshMin}
|
||||
/>
|
||||
<InputGroupText>{$_('time.minutes')}</InputGroupText>
|
||||
|
@ -212,6 +259,7 @@
|
|||
step="1"
|
||||
name="tzOffset"
|
||||
id="tzOffset"
|
||||
required
|
||||
bind:value={$settings.tzOffset}
|
||||
/>
|
||||
<InputGroupText>{$_('time.minutes')}</InputGroupText>
|
||||
|
@ -297,17 +345,23 @@
|
|||
>{$_('section.settings.bitaxeHostname')}</Label
|
||||
>
|
||||
<Col md="6">
|
||||
<Input
|
||||
type="text"
|
||||
bind:value={$settings.bitaxeHostname}
|
||||
name="bitaxeHostname"
|
||||
id="bitaxeHostname"
|
||||
bsSize={$uiSettings.inputSize}
|
||||
></Input>
|
||||
<InputGroup size={$uiSettings.inputSize}>
|
||||
<Input
|
||||
type="text"
|
||||
bind:value={$settings.bitaxeHostname}
|
||||
name="bitaxeHostname"
|
||||
valid={validBitaxe}
|
||||
id="bitaxeHostname"
|
||||
required
|
||||
></Input>
|
||||
<Button type="button" color="success" on:click={testBitaxe}
|
||||
>{$_('test', { default: 'Test' })}</Button
|
||||
>
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
{/if}
|
||||
{#if 'nostrZapNotify' in $settings}
|
||||
{#if 'nostrZapNotify' in $settings && $settings['nostrZapNotify']}
|
||||
<Row>
|
||||
<Label md={6} for="nostrZapPubkey" size={$uiSettings.inputSize}
|
||||
>{$_('section.settings.nostrZapPubkey')}</Label
|
||||
|
@ -318,10 +372,15 @@
|
|||
bind:value={$settings.nostrZapPubkey}
|
||||
name="nostrZapPubkey"
|
||||
id="nostrZapPubkey"
|
||||
on:change={checkValidNostrPubkey}
|
||||
on:change={() => checkValidNostrPubkey('nostrZapPubkey')}
|
||||
invalid={!isValidHexPubKey($settings.nostrZapPubkey)}
|
||||
bsSize={$uiSettings.inputSize}
|
||||
required
|
||||
minlength="64"
|
||||
></Input>
|
||||
{#if !isValidHexPubKey($settings.nostrZapPubkey)}
|
||||
<FormText>{$_('section.settings.invalidNostrPubkey')}</FormText>
|
||||
{/if}
|
||||
</Col>
|
||||
</Row>
|
||||
{/if}
|
||||
|
@ -336,10 +395,13 @@
|
|||
bind:value={$settings.nostrPubKey}
|
||||
name="nostrPubKey"
|
||||
id="nostrPubKey"
|
||||
on:change={checkValidNostrPubkey}
|
||||
on:change={() => checkValidNostrPubkey('nostrPubKey')}
|
||||
invalid={!isValidHexPubKey($settings.nostrPubKey)}
|
||||
bsSize={$uiSettings.inputSize}
|
||||
></Input>
|
||||
{#if !isValidHexPubKey($settings.nostrPubKey)}
|
||||
<FormText>{$_('section.settings.invalidNostrPubkey')}</FormText>
|
||||
{/if}
|
||||
</Col>
|
||||
</Row>
|
||||
{/if}
|
||||
|
@ -357,6 +419,7 @@
|
|||
id="nostrRelay"
|
||||
valid={validNostrRelay}
|
||||
bsSize={$uiSettings.inputSize}
|
||||
required
|
||||
></Input>
|
||||
<Button type="button" color="success" on:click={testNostrRelay}
|
||||
>{$_('test', { default: 'Test' })}</Button
|
||||
|
@ -378,6 +441,7 @@
|
|||
id="mempoolInstance"
|
||||
disabled={$settings.ownDataSource}
|
||||
bsSize="sm"
|
||||
required
|
||||
></Input>
|
||||
<InputGroupText>
|
||||
<Input
|
||||
|
@ -404,6 +468,8 @@
|
|||
name="hostnamePrefix"
|
||||
id="hostnamePrefix"
|
||||
bsSize={$uiSettings.inputSize}
|
||||
required
|
||||
minlength="1"
|
||||
></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -439,6 +505,7 @@
|
|||
min={1}
|
||||
step="1"
|
||||
bind:value={$settings.wpTimeout}
|
||||
required
|
||||
/>
|
||||
<InputGroupText>{$_('time.seconds')}</InputGroupText>
|
||||
</InputGroup>
|
||||
|
|
|
@ -44,6 +44,13 @@ const settingsJson = {
|
|||
ip: '192.168.20.231',
|
||||
txPower: 78,
|
||||
gitRev: '25d8b92bcbc8938417c140355ea3ba99ff9eb4b7',
|
||||
gitTag: '3.1.9',
|
||||
bitaxeEnabled: false,
|
||||
bitaxeHostname: 'bitaxe1',
|
||||
nostrZapNotify: true,
|
||||
hwRev: 'REV_A_EPD_2_13',
|
||||
fsRev: '4c5d9616212b27e3f05c35370f0befcf2c5a04b2',
|
||||
nostrZapPubkey: 'b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422',
|
||||
lastBuildTime: '1700666677',
|
||||
screens: [
|
||||
{ id: 0, name: 'Block Height', enabled: true },
|
||||
|
@ -187,6 +194,34 @@ test('info message when fetch eur price is enabled', async ({ page }) => {
|
|||
await expect(page.getByText('the WS Price connection will show')).toBeVisible();
|
||||
});
|
||||
|
||||
test('npub values will be converted to hex pubkeys', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
for (const field of ['#nostrZapPubkey']) {
|
||||
for (const val of ['npub1k5f85zx0xdskyayqpfpc0zq6n7vwqjuuxugkayk72fgynp34cs3qfcvqg2']) {
|
||||
await page.fill(field, val);
|
||||
|
||||
await page.getByLabel('Nostr Relay').click();
|
||||
const resultValue = await page.$eval(field, (input: HTMLInputElement) => input.value);
|
||||
|
||||
expect(resultValue).toBe('b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('empty nostr relay field is not accepted', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const nostrRelayField = page.getByLabel('Nostr Relay');
|
||||
|
||||
nostrRelayField.fill('');
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
const validationMessage = await nostrRelayField.evaluate((el) => el.validationMessage);
|
||||
|
||||
expect(validationMessage).toContain('Please fill out this field');
|
||||
});
|
||||
|
||||
test('screens should be able to change', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByRole('button', { name: 'Sats per Dollar' })).toBeVisible();
|
||||
|
|
Loading…
Reference in a new issue