fix(nodes): make node API tokens write-only (#5613)

* fix(nodes): make node API tokens write-only

* fix(nodes): keep token optional on edit for write-only API tokens

NodeView no longer returns apiToken, so the edit form must consume hasApiToken and not require re-entering the token. Relaxes the form validation on edit, adds a keep-current placeholder, and adds the i18n key to all 13 locales.
This commit is contained in:
n0ctal
2026-07-23 18:35:11 +05:00
committed by GitHub
parent 892c06c8bc
commit c77608bc47
29 changed files with 1716 additions and 88 deletions
+3 -1
View File
@@ -9,6 +9,7 @@ export const NodeRecordSchema = z.object({
port: z.number().optional(),
basePath: z.string().optional(),
apiToken: z.string().optional(),
hasApiToken: z.boolean().optional(),
enable: z.boolean().optional(),
status: z.string().optional(),
latencyMs: z.number().optional(),
@@ -67,6 +68,7 @@ export const NodeFormSchema = z.object({
// mTLS nodes authenticate via the client certificate, so the token is optional
// there; every other verify mode still requires one (matches remote.do()).
apiToken: z.string().trim(),
hasStoredToken: z.boolean().optional().default(false),
enable: z.boolean(),
allowPrivateAddress: z.boolean(),
tlsVerifyMode: z.enum(['verify', 'skip', 'pin', 'mtls']),
@@ -77,7 +79,7 @@ export const NodeFormSchema = z.object({
inboundTags: z.array(z.string()).nullish().transform((tags) => tags ?? []),
outboundTag: z.string().optional(),
}).superRefine((val, ctx) => {
if (val.tlsVerifyMode !== 'mtls' && val.apiToken.length === 0) {
if (val.tlsVerifyMode !== 'mtls' && val.apiToken.length === 0 && !val.hasStoredToken) {
ctx.addIssue({
code: 'custom',
path: ['apiToken'],