* Add dynamic Mikrotik peer support & UI/i18n
Introduce handling for dynamically created Mikrotik peers: add Dynamic/IsDynamic fields to domain, peer and interface models and API models; include "dynamic" in Mikrotik queries; skip updates/deletes for dynamic peers; sync dynamic flag when restoring state. Prevent modifying/deleting dynamic peers in manager. UI: disable selection/edit for dynamic peers and show badge. Implement Mikrotik interface hook execution. Add i18n keys/translations for dynamic-peer messages across languages.
* Fix Mikrotik hooks implementation and UI visibility
* fix: build OAuth return URL from the live location, not the Vite base
On base_path deployments, OAuth/OIDC login failed with a 400 "invalid
return URL" before the user ever reached the IdP.
LoginView and the router derived the app's runtime URL mount from
import.meta.env.BASE_URL, which is Vite's build-time *asset* base. Since
#711 set `base: './'` to fix relative asset loading (#710), BASE_URL is
"./", so `base_path: /wg` produced the return URL https://host/wg./#/login.
isValidReturnUrl() requires <base_path>/app, so every external-auth user
on a base_path deployment was locked out.
Derive the return URL from window.location instead: the app is mounted at
{base_path}/app/ in production and at / under `npm run dev`, so the live
document location is the only reliable source. Likewise drop the explicit
base from createWebHashHistory(), which then defaults to
`location.pathname + location.search` -- correct in every deployment.
This leaves the relative asset base from #711 untouched, so #710 stays
fixed, and it removes the last two readers of import.meta.env.BASE_URL
under frontend/src so the asset base can no longer affect routing.
Fixes#719
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Dan Berg <dan@webinargeek.com>
* fix: log rejected OAuth return URLs
The isValidReturnUrl() rejection was the only failure branch in
handleOauthInitiateGet without a slog call, and the 400 response body
reveals neither what was received nor what was expected. That is what
made #719 hard to diagnose.
Log both at Debug level, matching the neighbouring branches. The response
body is unchanged -- the URL is not echoed to the client.
Also note on the base-path test that the URL shape it pins is produced by
externalLogin() in frontend/src/views/LoginView.vue, so a future frontend
change has a breadcrumb back to the contract.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Dan Berg <dan@webinargeek.com>
---------
Signed-off-by: Dan Berg <dan@webinargeek.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: resolve Prism syntax highlighting error in peer config modal
The PeerViewModal and InterfaceViewModal components displayed:
Error: The language "undefined" has no grammar.
Root cause: vue-prism-component bundles its own instance of prismjs
(separate from the one imported elsewhere), so registering the ini
grammar on a different Prism instance had no effect on the one
actually performing the highlighting.
Fix: bypass vue-prism-component entirely. Import a single Prism
instance via a new helper (frontend/src/helpers/prism-setup.js) that
also registers the ini grammar, then render highlighted HTML directly
with <pre><code v-html="highlightedConfig">. This ensures the same
Prism object that owns the ini grammar is the one calling highlight().
Affected files:
- frontend/src/helpers/prism-setup.js (new): imports prismjs, defines
the ini grammar on the Prism instance, re-exports it
- frontend/src/components/PeerViewModal.vue: replaces <Prism> with
v-html using the shared Prism instance
- frontend/src/components/InterfaceViewModal.vue: same replacement
- frontend/src/main.js: removes the now-unused prism-setup import
Fixes#726
* Revert "fix: resolve Prism syntax highlighting error in peer config modal"
This reverts commit 8d1155224d.
* fix: resolve Prism syntax highlighting error in peer config modal
The PeerViewModal displayed: Error: The language "undefined" has no grammar.
Root cause: Vite bundled prismjs as separate instances per lazy-loaded
chunk, so the ini grammar registered in one instance was invisible to
vue-prism-component which used a different instance.
Fix:
- Add dedupe: ['prismjs'] to vite.config.mjs to force a single Prism
instance across all chunks
- Add the missing 'prismjs/components/prism-ini' import in
PeerViewModal.vue (InterfaceViewModal already had it)
Remove hardcoded `--base=/app/` from npm build script and set `base:
'./'` in vite.config to generate relative asset URLs
Update server `updateBasePathInFrontend` to handle relative paths
Fixes#710
Signed-off-by: Rich C <richcarni@gmail.com>
- Add frontend/src/lang/translations/ja.json (full translation of all 422 entries from en.json)
- Register ja in frontend/src/lang/index.js so it appears in the language selector
Tested locally with v2.2.3 build. UI strings render correctly in Japanese.
Closes: language support request
Co-authored-by: Taro Kawakami <tarokun@tunagufactory.jp>
* feat(frontend): add confirmation dialog before deleting users, peers, and interfaces (#652)
Add a browser confirm() dialog to the delete functions in UserEditModal,
PeerEditModal, and InterfaceEditModal to prevent accidental deletions.
The bulk-delete actions in UserView already had this protection; this
change brings single-item deletion in line with that behavior.
Translation keys (confirm-delete) added for all 10 supported locales:
de, en, es, fr, ko, pt, ru, uk, vi, zh.
Signed-off-by: LeC-D <leo.openc@gmail.com>
* fix broken translation files
---------
Signed-off-by: LeC-D <leo.openc@gmail.com>
Co-authored-by: Christoph Haas <christoph.h@sprinternet.at>
* mikrotik: allow to set DNS, wip: handle routes in wg-controller
* replace old route handling for local controller
* cleanup route handling for local backend
* implement route handling for mikrotik controller