Support token string from external file (#264)

* Support token string from external file

* Validate token source before saving config file
This commit is contained in:
Gerhard Tan
2025-08-17 14:34:09 +08:00
committed by GitHub
parent 1f5cf1df35
commit a0d0c057f7
10 changed files with 1189 additions and 1033 deletions

File diff suppressed because it is too large Load Diff

View File

@ -641,6 +641,27 @@
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
{
"id": "File",
"message": "File",
"translation": "File",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "Select Token File",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{
"id": "Source",
"message": "Source",
"translation": "Source",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -1012,6 +1033,13 @@
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "Token file is required.",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1976,16 +2004,16 @@
"fuzzy": true "fuzzy": true
}, },
{ {
"id": "Created", "id": "Number of TCP Connections",
"message": "Created", "message": "Number of TCP Connections",
"translation": "Created", "translation": "Number of TCP Connections",
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
{ {
"id": "Modified", "id": "Number of UDP Connections",
"message": "Modified", "message": "Number of UDP Connections",
"translation": "Modified", "translation": "Number of UDP Connections",
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
@ -1997,16 +2025,16 @@
"fuzzy": true "fuzzy": true
}, },
{ {
"id": "Number of TCP Connections", "id": "Created",
"message": "Number of TCP Connections", "message": "Created",
"translation": "Number of TCP Connections", "translation": "Created",
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
{ {
"id": "Number of UDP Connections", "id": "Modified",
"message": "Number of UDP Connections", "message": "Modified",
"translation": "Number of UDP Connections", "translation": "Modified",
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
@ -2160,13 +2188,6 @@
"translatorComment": "Copied from source.", "translatorComment": "Copied from source.",
"fuzzy": true "fuzzy": true
}, },
{
"id": "Source",
"message": "Source",
"translation": "Source",
"translatorComment": "Copied from source.",
"fuzzy": true
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -497,6 +497,21 @@
"message": "Token", "message": "Token",
"translation": "Simbólico" "translation": "Simbólico"
}, },
{
"id": "File",
"message": "File",
"translation": "Archivo"
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "Seleccionar archivo de token"
},
{
"id": "Source",
"message": "Source",
"translation": "Fuente"
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -762,6 +777,11 @@
"message": "UDP Packet Size", "message": "UDP Packet Size",
"translation": "Tamaño del paquete UDP" "translation": "Tamaño del paquete UDP"
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "Se requiere el archivo de token."
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1475,21 +1495,6 @@
} }
] ]
}, },
{
"id": "Created",
"message": "Created",
"translation": "Creado"
},
{
"id": "Modified",
"message": "Modified",
"translation": "Modificado"
},
{
"id": "Started",
"message": "Started",
"translation": "Empezado"
},
{ {
"id": "Number of TCP Connections", "id": "Number of TCP Connections",
"message": "Number of TCP Connections", "message": "Number of TCP Connections",
@ -1500,6 +1505,21 @@
"message": "Number of UDP Connections", "message": "Number of UDP Connections",
"translation": "Número de conexiones UDP" "translation": "Número de conexiones UDP"
}, },
{
"id": "Started",
"message": "Started",
"translation": "Empezado"
},
{
"id": "Created",
"message": "Created",
"translation": "Creado"
},
{
"id": "Modified",
"message": "Modified",
"translation": "Modificado"
},
{ {
"id": "{Name} Properties", "id": "{Name} Properties",
"message": "{Name} Properties", "message": "{Name} Properties",
@ -1610,11 +1630,6 @@
"message": "Error message", "message": "Error message",
"translation": "Mensaje de error" "translation": "Mensaje de error"
}, },
{
"id": "Source",
"message": "Source",
"translation": "Fuente"
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -507,6 +507,21 @@
"message": "Token", "message": "Token",
"translation": "トークン" "translation": "トークン"
}, },
{
"id": "File",
"message": "File",
"translation": "ファイル"
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "トークンファイルを選択"
},
{
"id": "Source",
"message": "Source",
"translation": "データソース"
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -772,6 +787,11 @@
"message": "UDP Packet Size", "message": "UDP Packet Size",
"translation": "UDPパケットサイズ" "translation": "UDPパケットサイズ"
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "トークンファイルが必要です。"
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1485,21 +1505,6 @@
} }
] ]
}, },
{
"id": "Created",
"message": "Created",
"translation": "作成時間"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修正時間"
},
{
"id": "Started",
"message": "Started",
"translation": "起動時間"
},
{ {
"id": "Number of TCP Connections", "id": "Number of TCP Connections",
"message": "Number of TCP Connections", "message": "Number of TCP Connections",
@ -1510,6 +1515,21 @@
"message": "Number of UDP Connections", "message": "Number of UDP Connections",
"translation": "UDP接続数" "translation": "UDP接続数"
}, },
{
"id": "Started",
"message": "Started",
"translation": "起動時間"
},
{
"id": "Created",
"message": "Created",
"translation": "作成時間"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修正時間"
},
{ {
"id": "{Name} Properties", "id": "{Name} Properties",
"message": "{Name} Properties", "message": "{Name} Properties",
@ -1620,11 +1640,6 @@
"message": "Error message", "message": "Error message",
"translation": "エラーメッセージ" "translation": "エラーメッセージ"
}, },
{
"id": "Source",
"message": "Source",
"translation": "データソース"
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -497,6 +497,21 @@
"message": "Token", "message": "Token",
"translation": "토큰" "translation": "토큰"
}, },
{
"id": "File",
"message": "File",
"translation": "파일"
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "토큰 파일 선택"
},
{
"id": "Source",
"message": "Source",
"translation": "데이터 소스"
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -762,6 +777,11 @@
"message": "UDP Packet Size", "message": "UDP Packet Size",
"translation": "UDP 패킷 크기" "translation": "UDP 패킷 크기"
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "토큰 파일이 필요합니다."
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1475,21 +1495,6 @@
} }
] ]
}, },
{
"id": "Created",
"message": "Created",
"translation": "창조 시간"
},
{
"id": "Modified",
"message": "Modified",
"translation": "수정 시간"
},
{
"id": "Started",
"message": "Started",
"translation": "시작 시간"
},
{ {
"id": "Number of TCP Connections", "id": "Number of TCP Connections",
"message": "Number of TCP Connections", "message": "Number of TCP Connections",
@ -1500,6 +1505,21 @@
"message": "Number of UDP Connections", "message": "Number of UDP Connections",
"translation": "UDP 연결 수" "translation": "UDP 연결 수"
}, },
{
"id": "Started",
"message": "Started",
"translation": "시작 시간"
},
{
"id": "Created",
"message": "Created",
"translation": "창조 시간"
},
{
"id": "Modified",
"message": "Modified",
"translation": "수정 시간"
},
{ {
"id": "{Name} Properties", "id": "{Name} Properties",
"message": "{Name} Properties", "message": "{Name} Properties",
@ -1610,11 +1630,6 @@
"message": "Error message", "message": "Error message",
"translation": "오류 메시지" "translation": "오류 메시지"
}, },
{
"id": "Source",
"message": "Source",
"translation": "데이터 소스"
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -497,6 +497,21 @@
"message": "Token", "message": "Token",
"translation": "令牌" "translation": "令牌"
}, },
{
"id": "File",
"message": "File",
"translation": "文件"
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "选择令牌文件"
},
{
"id": "Source",
"message": "Source",
"translation": "来源"
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -762,6 +777,11 @@
"message": "UDP Packet Size", "message": "UDP Packet Size",
"translation": "UDP 包大小" "translation": "UDP 包大小"
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "必须填写令牌文件。"
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1475,21 +1495,6 @@
} }
] ]
}, },
{
"id": "Created",
"message": "Created",
"translation": "创建时间"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修改时间"
},
{
"id": "Started",
"message": "Started",
"translation": "启动时间"
},
{ {
"id": "Number of TCP Connections", "id": "Number of TCP Connections",
"message": "Number of TCP Connections", "message": "Number of TCP Connections",
@ -1500,6 +1505,21 @@
"message": "Number of UDP Connections", "message": "Number of UDP Connections",
"translation": "UDP 连接数" "translation": "UDP 连接数"
}, },
{
"id": "Started",
"message": "Started",
"translation": "启动时间"
},
{
"id": "Created",
"message": "Created",
"translation": "创建时间"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修改时间"
},
{ {
"id": "{Name} Properties", "id": "{Name} Properties",
"message": "{Name} Properties", "message": "{Name} Properties",
@ -1610,11 +1630,6 @@
"message": "Error message", "message": "Error message",
"translation": "错误消息" "translation": "错误消息"
}, },
{
"id": "Source",
"message": "Source",
"translation": "来源"
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -497,6 +497,21 @@
"message": "Token", "message": "Token",
"translation": "權杖" "translation": "權杖"
}, },
{
"id": "File",
"message": "File",
"translation": "檔案"
},
{
"id": "Select Token File",
"message": "Select Token File",
"translation": "選擇權杖檔案"
},
{
"id": "Source",
"message": "Source",
"translation": "來源"
},
{ {
"id": "Secret", "id": "Secret",
"message": "Secret", "message": "Secret",
@ -762,6 +777,11 @@
"message": "UDP Packet Size", "message": "UDP Packet Size",
"translation": "UDP 封包大小" "translation": "UDP 封包大小"
}, },
{
"id": "Token file is required.",
"message": "Token file is required.",
"translation": "必須填寫權杖檔案。"
},
{ {
"id": "Config already exists", "id": "Config already exists",
"message": "Config already exists", "message": "Config already exists",
@ -1475,21 +1495,6 @@
} }
] ]
}, },
{
"id": "Created",
"message": "Created",
"translation": "建立日期"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修改日期"
},
{
"id": "Started",
"message": "Started",
"translation": "啟動日期"
},
{ {
"id": "Number of TCP Connections", "id": "Number of TCP Connections",
"message": "Number of TCP Connections", "message": "Number of TCP Connections",
@ -1500,6 +1505,21 @@
"message": "Number of UDP Connections", "message": "Number of UDP Connections",
"translation": "UDP 連線數" "translation": "UDP 連線數"
}, },
{
"id": "Started",
"message": "Started",
"translation": "啟動日期"
},
{
"id": "Created",
"message": "Created",
"translation": "建立日期"
},
{
"id": "Modified",
"message": "Modified",
"translation": "修改日期"
},
{ {
"id": "{Name} Properties", "id": "{Name} Properties",
"message": "{Name} Properties", "message": "{Name} Properties",
@ -1610,11 +1630,6 @@
"message": "Error message", "message": "Error message",
"translation": "錯誤訊息" "translation": "錯誤訊息"
}, },
{
"id": "Source",
"message": "Source",
"translation": "來源"
},
{ {
"id": "This feature only supports text in INI or TOML format.", "id": "This feature only supports text in INI or TOML format.",
"message": "This feature only supports text in INI or TOML format.", "message": "This feature only supports text in INI or TOML format.",

View File

@ -22,6 +22,8 @@ type ClientAuth struct {
AuthenticateHeartBeats bool `ini:"authenticate_heartbeats,omitempty" token:"true" oidc:"true"` AuthenticateHeartBeats bool `ini:"authenticate_heartbeats,omitempty" token:"true" oidc:"true"`
AuthenticateNewWorkConns bool `ini:"authenticate_new_work_conns,omitempty" token:"true" oidc:"true"` AuthenticateNewWorkConns bool `ini:"authenticate_new_work_conns,omitempty" token:"true" oidc:"true"`
Token string `ini:"token,omitempty" token:"true"` Token string `ini:"token,omitempty" token:"true"`
TokenSource string `ini:"-" token:"true"`
TokenSourceFile string `ini:"-" token:"true"`
OIDCClientId string `ini:"oidc_client_id,omitempty" oidc:"true"` OIDCClientId string `ini:"oidc_client_id,omitempty" oidc:"true"`
OIDCClientSecret string `ini:"oidc_client_secret,omitempty" oidc:"true"` OIDCClientSecret string `ini:"oidc_client_secret,omitempty" oidc:"true"`
OIDCAudience string `ini:"oidc_audience,omitempty" oidc:"true"` OIDCAudience string `ini:"oidc_audience,omitempty" oidc:"true"`
@ -37,9 +39,15 @@ func (ca ClientAuth) Complete() ClientAuth {
ca = auth.(ClientAuth) ca = auth.(ClientAuth)
ca.AuthMethod = authMethod ca.AuthMethod = authMethod
} }
// Check the default auth method if authMethod == consts.AuthToken {
if authMethod == consts.AuthToken && ca.Token == "" { if ca.TokenSource != "" {
ca.AuthMethod = "" ca.Token = ""
} else {
ca.TokenSourceFile = ""
if ca.Token == "" {
ca.AuthMethod = ""
}
}
} }
} else { } else {
ca = ClientAuth{} ca = ClientAuth{}
@ -408,6 +416,9 @@ func (conf *ClientConfig) saveTOML(path string) error {
// Otherwise, it should be completed for file written to disk. // Otherwise, it should be completed for file written to disk.
func (conf *ClientConfig) Complete(read bool) { func (conf *ClientConfig) Complete(read bool) {
// Common config // Common config
if conf.LegacyFormat {
conf.TokenSource = ""
}
conf.ClientAuth = conf.ClientAuth.Complete() conf.ClientAuth = conf.ClientAuth.Complete()
if conf.AdminPort == 0 { if conf.AdminPort == 0 {
conf.AdminUser = "" conf.AdminUser = ""

View File

@ -21,6 +21,15 @@ func ClientCommonFromV1(c *v1.ClientCommonConfig) (r ClientCommon) {
// Auth client config // Auth client config
r.AuthMethod = string(c.Auth.Method) r.AuthMethod = string(c.Auth.Method)
r.Token = c.Auth.Token r.Token = c.Auth.Token
if ts := c.Auth.TokenSource; ts != nil {
r.TokenSource = ts.Type
switch ts.Type {
case "file":
if ts.File != nil {
r.TokenSourceFile = ts.File.Path
}
}
}
r.OIDCClientId = c.Auth.OIDC.ClientID r.OIDCClientId = c.Auth.OIDC.ClientID
r.OIDCClientSecret = c.Auth.OIDC.ClientSecret r.OIDCClientSecret = c.Auth.OIDC.ClientSecret
r.OIDCAudience = c.Auth.OIDC.Audience r.OIDCAudience = c.Auth.OIDC.Audience
@ -260,6 +269,13 @@ func ClientCommonToV1(c *ClientCommon) (r v1.ClientCommonConfig) {
AdditionalEndpointParams: c.OIDCAdditionalEndpointParams, AdditionalEndpointParams: c.OIDCAdditionalEndpointParams,
}, },
} }
if c.TokenSource != "" {
r.Auth.TokenSource = &v1.ValueSource{Type: c.TokenSource}
switch c.TokenSource {
case "file":
r.Auth.TokenSource.File = &v1.FileSource{Path: c.TokenSourceFile}
}
}
if c.AuthenticateHeartBeats { if c.AuthenticateHeartBeats {
r.Auth.AdditionalScopes = append(r.Auth.AdditionalScopes, v1.AuthScopeHeartBeats) r.Auth.AdditionalScopes = append(r.Auth.AdditionalScopes, v1.AuthScopeHeartBeats)
} }
@ -647,6 +663,9 @@ func toMap(in any, tag string) (map[string]any, error) {
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
ft := t.Field(i) ft := t.Field(i)
fv := v.Field(i) fv := v.Field(i)
if fv.Kind() == reflect.Ptr && fv.Elem().Kind() == reflect.Struct {
fv = fv.Elem()
}
key := ft.Tag.Get(tag) key := ft.Tag.Get(tag)
if key != "" { if key != "" {
key = strings.Split(key, ",")[0] key = strings.Split(key, ",")[0]

View File

@ -106,7 +106,9 @@ func (cd *EditClientDialog) basicConfPage() TabPage {
} }
func (cd *EditClientDialog) authConfPage() TabPage { func (cd *EditClientDialog) authConfPage() TabPage {
token := Bind("tokenCheck.Checked") tokenSource := Bind("tokenCheck.Checked && !legacyFormat.Checked")
tokenInput := Bind("tokenCheck.Checked && (legacyFormat.Checked || tokenSource.Value == '')")
tokenFile := Bind("tokenSource.Visible && tokenSource.Value == 'file'")
oidc := Bind("oidcCheck.Checked") oidc := Bind("oidcCheck.Checked")
auth := Bind("!noAuthCheck.Checked") auth := Bind("!noAuthCheck.Checked")
return AlignGrid(TabPage{ return AlignGrid(TabPage{
@ -119,8 +121,20 @@ func (cd *EditClientDialog) authConfPage() TabPage {
{Name: "oidcCheck", Text: "OIDC", Value: consts.AuthOIDC}, {Name: "oidcCheck", Text: "OIDC", Value: consts.AuthOIDC},
{Name: "noAuthCheck", Text: i18n.Sprintf("None"), Value: ""}, {Name: "noAuthCheck", Text: i18n.Sprintf("None"), Value: ""},
}), }),
Label{Visible: token, Text: i18n.SprintfColon("Token")}, Label{Visible: tokenInput, Text: i18n.SprintfColon("Token")},
LineEdit{Visible: token, Text: Bind("Token"), PasswordMode: true}, LineEdit{Visible: tokenInput, Text: Bind("Token"), PasswordMode: true},
Label{Visible: tokenFile, Text: i18n.SprintfColon("File")},
NewBrowseLineEdit(nil, tokenFile, true, Bind("TokenSourceFile"),
i18n.Sprintf("Select Token File"), "", true),
Label{Visible: tokenSource, Text: i18n.SprintfColon("Source")},
ComboBox{
Name: "tokenSource",
Visible: tokenSource,
Value: Bind("TokenSource"),
Model: NewListModel([]string{"", "file"}, i18n.Sprintf("None"), i18n.Sprintf("File")),
BindingMember: "Value",
DisplayMember: "Title",
},
Label{Visible: oidc, Text: "ID:"}, Label{Visible: oidc, Text: "ID:"},
LineEdit{Visible: oidc, Text: Bind("OIDCClientId")}, LineEdit{Visible: oidc, Text: Bind("OIDCClientId")},
Label{Visible: oidc, Text: i18n.SprintfColon("Secret")}, Label{Visible: oidc, Text: i18n.SprintfColon("Secret")},
@ -472,6 +486,10 @@ func (cd *EditClientDialog) onSave() {
return return
} }
} }
if !newConf.LegacyFormat && newConf.TokenSource == "file" && newConf.TokenSourceFile == "" {
showErrorMessage(cd.Form(), "", i18n.Sprintf("Token file is required."))
return
}
cd.data.ClientCommon = newConf.ClientCommon cd.data.ClientCommon = newConf.ClientCommon
cd.data.ClientCommon.Name = newConf.Name cd.data.ClientCommon.Name = newConf.Name
cd.Accept() cd.Accept()