mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-06-06 13:11:53 -07:00
Add config UI for webdav uploader
This commit is contained in:
committed by
Markus Unterwaditzer
parent
e7ffebbb30
commit
3fcd908d68
@@ -46,8 +46,8 @@ pub struct Config {
|
|||||||
pub wifi_enabled: bool,
|
pub wifi_enabled: bool,
|
||||||
/// Vector containing wifi client DNS servers
|
/// Vector containing wifi client DNS servers
|
||||||
pub dns_servers: Option<Vec<String>>,
|
pub dns_servers: Option<Vec<String>>,
|
||||||
/// Optional WebDAV upload configuration. When unset, no upload worker runs.
|
/// WebDAV upload configuration. The upload worker runs whenever `webdav.url` is non-empty.
|
||||||
pub webdav: Option<WebdavConfig>,
|
pub webdav: WebdavConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for uploading finished QMDL recordings to a WebDAV server.
|
/// Configuration for uploading finished QMDL recordings to a WebDAV server.
|
||||||
@@ -105,7 +105,7 @@ impl Default for Config {
|
|||||||
wifi_security: None,
|
wifi_security: None,
|
||||||
wifi_enabled: false,
|
wifi_enabled: false,
|
||||||
dns_servers: None,
|
dns_servers: None,
|
||||||
webdav: None,
|
webdav: WebdavConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -288,12 +288,12 @@ async fn run_with_config(
|
|||||||
wifi_status.clone(),
|
wifi_status.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(webdav_config) = config.webdav.clone() {
|
if !config.webdav.url.trim().is_empty() {
|
||||||
run_webdav_upload_worker(
|
run_webdav_upload_worker(
|
||||||
&task_tracker,
|
&task_tracker,
|
||||||
shutdown_token.clone(),
|
shutdown_token.clone(),
|
||||||
qmdl_store_lock.clone(),
|
qmdl_store_lock.clone(),
|
||||||
webdav_config.into(),
|
config.webdav.clone().into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,15 @@
|
|||||||
let scanning = $state(false);
|
let scanning = $state(false);
|
||||||
let scanResults = $state<WifiNetwork[]>([]);
|
let scanResults = $state<WifiNetwork[]>([]);
|
||||||
let dnsServersInput = $state('');
|
let dnsServersInput = $state('');
|
||||||
|
let webdavExpanded = $state(false);
|
||||||
|
let webdavUrlInput = $state<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
async function load_config() {
|
async function load_config() {
|
||||||
try {
|
try {
|
||||||
loading = true;
|
loading = true;
|
||||||
config = await get_config();
|
config = await get_config();
|
||||||
dnsServersInput = config.dns_servers ? config.dns_servers.join(', ') : '';
|
dnsServersInput = config.dns_servers ? config.dns_servers.join(', ') : '';
|
||||||
|
webdavExpanded = config.webdav.url.trim() !== '';
|
||||||
message = '';
|
message = '';
|
||||||
messageType = null;
|
messageType = null;
|
||||||
poll_wifi_status();
|
poll_wifi_status();
|
||||||
@@ -345,6 +348,173 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="border-t border-gray-200 pt-4 mt-6 space-y-3">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-800 mb-4">WebDAV Upload</h3>
|
||||||
|
<p class="text-xs text-gray-500">
|
||||||
|
Once a recording has been closed for at least the configured age, both the
|
||||||
|
.qmdl and .ndjson files are uploaded in the background to the WebDAV server.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
<input
|
||||||
|
id="webdav_enabled"
|
||||||
|
type="checkbox"
|
||||||
|
checked={webdavExpanded}
|
||||||
|
onchange={(e) => {
|
||||||
|
webdavExpanded = e.currentTarget.checked;
|
||||||
|
if (webdavExpanded) {
|
||||||
|
setTimeout(() => webdavUrlInput?.focus(), 0);
|
||||||
|
} else {
|
||||||
|
if (config) config.webdav.url = '';
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
class="h-4 w-4 text-rayhunter-blue focus:ring-rayhunter-blue border-gray-300 rounded-sm"
|
||||||
|
/>
|
||||||
|
<label for="webdav_enabled" class="ml-2 block text-sm text-gray-700">
|
||||||
|
Enable WebDAV upload
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if webdavExpanded}
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_url"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Server URL
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_url"
|
||||||
|
type="url"
|
||||||
|
bind:this={webdavUrlInput}
|
||||||
|
bind:value={config.webdav.url}
|
||||||
|
onblur={() => {
|
||||||
|
if (config && config.webdav.url.trim() === '') {
|
||||||
|
webdavExpanded = false;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
placeholder="https://dav.example.com/rayhunter/"
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
Files are uploaded via HTTP PUT under this base URL. No folders are
|
||||||
|
created, and folders in this base URL are assumed to exist already.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_username"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Username
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_username"
|
||||||
|
type="text"
|
||||||
|
bind:value={config.webdav.username}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
Optional. Leave blank for unauthenticated uploads.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_password"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_password"
|
||||||
|
type="password"
|
||||||
|
bind:value={config.webdav.password}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
A password without a username will be rejected and the request will
|
||||||
|
be sent unauthenticated.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_upload_timeout_secs"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Upload Timeout (seconds)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_upload_timeout_secs"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
bind:value={config.webdav.upload_timeout_secs}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_poll_interval_secs"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Poll Interval (seconds)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_poll_interval_secs"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
bind:value={config.webdav.poll_interval_secs}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
How often the worker checks for new entries to upload.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="webdav_min_age_secs"
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
Minimum Age Before Upload (seconds)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="webdav_min_age_secs"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
bind:value={config.webdav.min_age_secs}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-hidden focus:ring-2 focus:ring-rayhunter-blue"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-gray-500 mt-1">
|
||||||
|
How long a recording must be closed before it becomes eligible for
|
||||||
|
upload.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
<input
|
||||||
|
id="webdav_delete_on_upload"
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={config.webdav.delete_on_upload}
|
||||||
|
class="h-4 w-4 text-rayhunter-blue focus:ring-rayhunter-blue border-gray-300 rounded-sm"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
for="webdav_delete_on_upload"
|
||||||
|
class="ml-2 block text-sm text-gray-700"
|
||||||
|
>
|
||||||
|
Delete on successful upload
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-gray-500">
|
||||||
|
When enabled, the local files are removed after a successful upload.
|
||||||
|
Otherwise the manifest is just marked as uploaded.
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if config.device === 'orbic' || config.device === 'moxee' || config.device === 'tmobile' || config.device === 'wingtech'}
|
{#if config.device === 'orbic' || config.device === 'moxee' || config.device === 'tmobile' || config.device === 'wingtech'}
|
||||||
<div class="border-t border-gray-200 pt-4 mt-6 space-y-3">
|
<div class="border-t border-gray-200 pt-4 mt-6 space-y-3">
|
||||||
<h3 class="text-lg font-semibold text-gray-800 mb-4">WiFi Client Mode</h3>
|
<h3 class="text-lg font-semibold text-gray-800 mb-4">WiFi Client Mode</h3>
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ export enum enabled_notifications {
|
|||||||
LowBattery = 'LowBattery',
|
LowBattery = 'LowBattery',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WebdavConfig {
|
||||||
|
url: string;
|
||||||
|
username: string | null;
|
||||||
|
password: string | null;
|
||||||
|
upload_timeout_secs: number;
|
||||||
|
poll_interval_secs: number;
|
||||||
|
min_age_secs: number;
|
||||||
|
delete_on_upload: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
device: string;
|
device: string;
|
||||||
ui_level: number;
|
ui_level: number;
|
||||||
@@ -33,6 +43,9 @@ export interface Config {
|
|||||||
wifi_security: 'wpa_psk' | 'sae' | null;
|
wifi_security: 'wpa_psk' | 'sae' | null;
|
||||||
wifi_enabled: boolean;
|
wifi_enabled: boolean;
|
||||||
dns_servers: string[] | null;
|
dns_servers: string[] | null;
|
||||||
|
firewall_restrict_outbound: boolean;
|
||||||
|
firewall_allowed_ports: number[] | null;
|
||||||
|
webdav: WebdavConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WifiStatus {
|
export interface WifiStatus {
|
||||||
|
|||||||
Reference in New Issue
Block a user