19 Commits
Author SHA1 Message Date
alex 1bdd176c18 App logs, client settings, NavMenu layout
- Add real-time app logs via SignalR (log level, category filters)
- Add filters modal with restore defaults; sentinel for empty arrays
- Add client settings: max lines and auto-scroll per log panel
- Improve NavMenu: align settings + hamburger, smaller mobile logo
- LogsService, LogsHub, LoggingController, AppLogsLoggerProvider
- Persist log level and filters to appsettings.Overrides.json
2026-02-10 08:44:30 +10:00
alex d06d6ef6c9 install.sh: add jq_release helper, mktemp for zip, trim URL in find_asset_url, fix validation indentation 2026-02-05 23:48:14 +10:00
alex 1dffdcf2ed install.sh: strip control chars from GitHub API JSON so jq parses release body
GitHub can return release body with unescaped control characters (e.g. from
generated release notes); jq rejects them. Sanitize response in fetch_release
and list_releases before piping to jq (keep \n and \r).
2026-02-05 23:28:10 +10:00
alex 23bf6bb9e0 install.sh: fix collect_config under set -e when no config
- Use set +e around env/grep/read so grep (no match), read (EOF), and
  [ -f ]/[ -s ] do not exit the script when no DNSMASQ_WEBUI_* or --set
- Write env vars to temp file .env then read; only process when file
  exists and is non-empty
- Add || true after [ -s CONFIG_SET_FILE ] && cat so empty CONFIG_SET_FILE
  does not trigger exit
Fixes install/update with no config (e.g. plain --version/--update --dir)
failing silently under sh (dash).
2026-02-05 04:04:56 +10:00
alex dfb0b94e4a install.sh: fix no output when run as curl | sh
- Echo 'Installing dnsmasq-webui...' at start of do_install so output is visible
- Use </dev/null on all curl calls so they do not consume stdin; when run
  as 'curl | sh' the script was being eaten and exited before any echo
2026-02-05 03:51:52 +10:00
alex b38f278a1f Install script: config at install (--set, DNSMASQ_WEBUI_*), env file for service
- Add --set KEY=VALUE and env vars DNSMASQ_WEBUI_* to configure app at install
- Write env file for systemd (system: /etc/default/dnsmasq-webui; user: install-dir/dnsmasq-webui.env)
- Default ASPNETCORE_URLS=http://0.0.0.0:8080 so service listens on 8080
- Preserve existing env file on update (only overwrite when new config or first install)
- README: configure-at-install section, --set in options table, update preserves env note
2026-02-05 02:50:43 +10:00
alex e284388828 Fix install script: use RELEASE_TAG to avoid clash with os-release VERSION 2026-02-05 02:20:58 +10:00
alex d6a7dd29ff Fix install script URL handling and README quickstart
- README: use master branch in raw GitHub URL (repo default branch)
- install.sh: trim repo and asset URLs (fix malformed URL when script has CRLF or trailing whitespace)
2026-02-05 02:15:30 +10:00
alex 2f049feed2 Install script, static assets, UI and release workflow updates
- install.sh: default dirs, --update/--service/--uninstall/--purge, in-dir dnsmasq-webui symlink, ContentRootPath note
- UseStaticFiles instead of MapStaticAssets (fix 0-byte assets)
- Program: ContentRootPath when not Development for symlink/CWD
- App.razor: direct asset paths
- Dnsmasq page: remove redundant status pre, margin above Reload button
- Sidebar: logo 64px via app.css, hamburger vertically centered, toggler inside top-row
- ApplicationTitle documented in README
- publish/release: RIDs, Docker build for glibc
2026-02-05 02:00:36 +10:00
alex 4ff9c552eb Prepare release 0.0.1: install script (uninstall/purge, service, validation), README (how to use, config), UI and effective config updates 2026-02-05 00:05:52 +10:00
alex 8c411b8d09 Add LICENSE, README, logo; update install script, nav, favicon, App 2026-02-04 21:55:52 +10:00
alex 633c1ef827 Effective config refactor, remove dead parser path, add source line numbers
Effective config:
- Add EffectiveConfigFieldDescriptor (metadata + value/source/items delegates)
- Add EffectiveConfigFieldBuilder with Config/Sources/Items helpers; build all
  fields when EffectiveConfig present (empty = not set); empty list when null
- Add EffectiveConfigSectionPanel + EffectiveConfigFieldDisplay; section CSS
  uses ::deep for child markup, open-state styling for headers
- Remove Kind from descriptor (use DnsmasqConfOptionRegistry.GetKind(OptionName)
  when needed)

Dead code removal:
- Remove DnsmasqOptionModels, ParsedDirective (DnsmasqConfDirective),
  DnsmasqOptionKind, DnsmasqConfOptionRegistry
- Remove ParseLine from DnsmasqConfDirectiveParser; keep StripComment and
  TryParseKeyValue (used by DnsmasqConfIncludeParser)
- Simplify DnsmasqConfDirectiveParserTests; remove DnsmasqConfOptionRegistryTests

ConfigValueSource:
- Add LineNumber (int?); IncludeParser passes 1-based line to MakeSource
- GetReadOnlyTooltip includes 'line N' when LineNumber set
- Add ConfigValueSourceTests; assert LineNumber in IncludeParser WithSource tests

Also: .github/workflows/release.yml, scripts/install.sh, script tweaks
2026-02-04 20:23:59 +10:00
alex a8ddcdec4e Dnsmasq/Hosts UI tweaks, test harness: down before redeploy, exclude leases from mount
- Dnsmasq page: Config (Main config, Managed file, Config set) under Service configuration; remove Paths/Leases (in Effective config DHCP); EffectiveConfigSection collapsible groups; StatusSection flex-wrap
- Hosts: HostsFileSection always shows table; 'No host entries' in tbody when empty
- Models: reorganize into sub-namespaces (Config, EffectiveConfig, Hosts, Dhcp, Status); move EffectiveConfig/Status/Logs components under Dnsmasq
- Test harness: prepare-test-mount.sh runs 'docker compose down' before mount+up so all containers (including DHCP clients) restart; exclude testdata/leases from sync (unit tests only); testdata/README
2026-02-03 01:35:26 +10:00
alex a60d0e8db8 DHCP: read-only hosts from other configs, combobox inputs, polling, UI fixes
- Static hosts: read dhcp-host from all config files; show external as read-only
  with Source column; IsEditable + SourcePath on DhcpHostEntry; reject save if
  managed entry duplicates MAC from another file (400 + message)
- Lease field: single input + datalist (type or select), remove Other dropdown
- MAC field: single input + datalist from current leases, TryFillFromLeaseByMac
- Add host: default Name=*, suggest next free IP from DHCP range
- Leases: configurable refresh polling; Settings modal for interval (client-side)
- DhcpHostsClient: surface 400 error body message on save failure
- App title config (ApplicationOptions), nav/layout/error/hosts tweaks
2026-02-02 00:40:53 +10:00
alex e50cfc986c WIP: layout, status, hosts, dhcp, error pages and tests 2026-02-01 17:05:37 +10:00
alex d0391ef058 Effective config, hosts/addn-hosts logic, test harness status & logs
- EffectiveDnsmasqConfig: overridable single-value options (no-hosts, addn-hosts,
  flags, dhcp-leasefile, cache-size, port, etc.) from dnsmasq source/docs.
- Hosts UI: allow editing when no-hosts but SystemHostsPath is in addn-hosts;
  HostsController and Hosts.razor check pathInAddnHosts.
- Config comments: managed file ensures one addn-hosts line in our file only;
  DnsmasqOptions/validator docs for SystemHostsPath and addn-hosts.
- Test harness: dnsmasq logs to /data/dnsmasq.log (log-facility + log-queries in
  dnsmasq-test.conf); entrypoint touches log file for write access.
- dnsmasq-status.sh: simulates systemctl status output in container (ps/pgrep);
  Dockerfile copies and chmod +x; StatusShowCommand/LogsCommand use script and
  tail /data/dnsmasq.log.
- Project: Models/Config namespace, typed HTTP clients, combined DHCP+Leases
  page, ProcessRunner, shared models (PascalCase).
2026-02-01 01:17:32 +10:00
alex 5bd9eaf55d Options validation, CORS, HTTPS, HttpClient factory, config error output
- DnsmasqOptionsValidator: fail-fast at startup if MainConfigPath/HostsPath
  missing or files do not exist; clear stderr message before exit
- Program: AddOptions + ValidateOnStart; catch OptionsValidationException,
  print prominent error and Environment.Exit(1)
- CORS: configurable via Cors:Enabled, Cors:PolicyName, AllowedOrigins, etc.
  (appsettings + env); default disabled
- HTTPS: ForwardedHeaders (when enabled) and Https:UseRedirectAndHsts
  (appsettings + env); default disabled
- HttpClient: IHttpClientFactory + SameHostBaseAddressHandler for same-host
  API calls; default client uses Options.DefaultName
- publish-self-contained.sh: platform auto-detect, clean before publish,
  --no-clean option, RIDs including ubuntu.*-x64/arm64, linux-musl-*
- prepare-test-mount.sh: stop/tidy options
- EnsureManagedConfigHostedService / DnsmasqConfigSetService: managed
  config path and conf-file= handling
- appsettings: ForwardedHeaders, Https, Cors sections; Dnsmasq defaults

Note: Dockerfile.dnsmasq removed (may need restore for app+dnsmasq image)
2026-01-31 22:30:18 +10:00
alex 40fbf14327 Refactor parsers to Superpower; config set; EnsureManagedConfig; options doc
- Parsers: Superpower for all (Directive, FileLine, Include, DhcpHost, Leases, Hosts)
- Shared ConfParserHelpers (Token, OptionalCommentPrefix)
- DnsmasqConfOptionRegistry + DnsmasqOptionKind: typed options (ConfFile, ConfDir,
  Domain, DhcpRange, Server, Local, Address, DhcpOption, DhcpHost, Path, Flag, etc.)
- EnsureManagedConfigHostedService: append conf-dir= to main config if missing,
  then create managed file; DnsmasqOptions + Dockerfile comments for permissions
- Renames: ConfigLine->DnsmasqConfLine, ConfigSet->DnsmasqConfigSet, etc.
- Test harness: entrypoint in scripts/, prepare-test-mount improvements
- Status/Reload API and UI: stdout+stderr, exit code
2026-01-31 19:28:10 +10:00
alex f5bbe7d608 Refactor: ServiceCollectionExtensions data-driven registration; LeasesCache + FSW; test harness scripts 2026-01-31 09:49:10 +10:00