diff --git a/internal/admin/handler.go b/internal/admin/handler.go index 4263ec4437..716db06aaf 100644 --- a/internal/admin/handler.go +++ b/internal/admin/handler.go @@ -696,6 +696,28 @@ func (h *Handler) ListVariables(c *gin.Context) { success(c, variable, "") } +// ShowVariable handle show variable +func (h *Handler) ShowVariable(c *gin.Context) { + encodedVarName := c.Param("var_name") + varName, err := common.DecodeFromBase64(encodedVarName) + if err != nil { + errorResponse(c, err.Error(), 400) + return + } + if varName == "" { + errorResponse(c, "Var name is required", 400) + return + } + + variable, err := h.service.GetVariable(varName) + if err != nil { + errorResponse(c, err.Error(), 500) + return + } + + success(c, variable, "") +} + // SetVariableHTTPRequest set variable request type SetVariableHTTPRequest struct { VarName string `json:"var_name" binding:"required"` diff --git a/internal/admin/router.go b/internal/admin/router.go index e728397b6e..abcc064a1c 100644 --- a/internal/admin/router.go +++ b/internal/admin/router.go @@ -80,6 +80,7 @@ func (r *Router) Setup(engine *gin.Engine) { // Variables/Settings protected.GET("/variables", r.handler.ListVariables) protected.PUT("/variables", r.handler.SetVariable) + protected.GET("/variables/:var_name", r.handler.ShowVariable) // Configs protected.GET("/configs", r.handler.ListConfigs) diff --git a/internal/cli/admin_command.go b/internal/cli/admin_command.go index 1858e9ba3e..13c02ccc43 100644 --- a/internal/cli/admin_command.go +++ b/internal/cli/admin_command.go @@ -975,9 +975,11 @@ func (c *CLI) AdminShowVariable(cmd *Command) (ResponseIf, error) { return nil, fmt.Errorf("var_name not provided") } - payload := map[string]interface{}{"var_name": varName} + encodedVarName := common.EncodeToBase64(varName) - resp, err := c.AdminServerClient.Request("GET", "/admin/variables", "admin", nil, payload) + endPoint := fmt.Sprintf("/admin/variables/%s", encodedVarName) + + resp, err := c.AdminServerClient.Request("GET", endPoint, "admin", nil, nil) if err != nil { return nil, fmt.Errorf("failed to show variable: %w", err) } diff --git a/internal/cli/cli_http.go b/internal/cli/cli_http.go index 7306db0a56..c4689adcde 100644 --- a/internal/cli/cli_http.go +++ b/internal/cli/cli_http.go @@ -330,6 +330,8 @@ func (c *CLI) ExecuteUserCommand(cmd *Command) (ResponseIf, error) { return c.APISetAPIKeyCommand(cmd) case "api_set_variable": return c.APISetVariableCommand(cmd) + case "api_show_variable": + return c.APIShowVariableCommand(cmd) case "api_unset_api_key": return c.APIUnsetAPIKeyCommand(cmd) case "api_show_version": diff --git a/internal/cli/user_command.go b/internal/cli/user_command.go index 72867467db..4a4174f144 100644 --- a/internal/cli/user_command.go +++ b/internal/cli/user_command.go @@ -1146,6 +1146,51 @@ func (c *CLI) APISetVariableCommand(cmd *Command) (ResponseIf, error) { return &result, nil } +// APIShowVariableCommand displays variable value +func (c *CLI) APIShowVariableCommand(cmd *Command) (ResponseIf, error) { + + if c.Config.CLIMode != APIMode { + return nil, fmt.Errorf("this command is only allowed in USER mode") + } + + httpClient := c.APIServerClientMap[c.Config.APIClientConfig.CurrentAPIServer] + + if httpClient.APIKey == nil && httpClient.LoginToken == nil { + return nil, fmt.Errorf("API key not set. Please login first") + } + + varName, ok := cmd.Params["var_name"].(string) + if !ok { + return nil, fmt.Errorf("var_name not provided") + } + + EncodedVarName := common.EncodeToBase64(varName) + + endPoint := fmt.Sprintf("/system/variables/%s", EncodedVarName) + + resp, err := httpClient.Request("GET", endPoint, "web", nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to get variable: %w", err) + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("failed to get variable: HTTP %d, body: %s", resp.StatusCode, string(resp.Body)) + } + + var result CommonResponse + if err = json.Unmarshal(resp.Body, &result); err != nil { + return nil, fmt.Errorf("show variable failed: invalid JSON (%w)", err) + } + + if result.Code != 0 { + return nil, fmt.Errorf("%s", result.Message) + } + + normalizeVariableRows(result.Data) + result.Duration = resp.Duration + return &result, nil +} + // APIShowAPIKeyCommand displays the current API key func (c *CLI) APIShowAPIKeyCommand(cmd *Command) (ResponseIf, error) { if c.Config.CLIMode != APIMode { diff --git a/internal/cli/user_parser.go b/internal/cli/user_parser.go index 8cfc48c7f3..f952969c06 100644 --- a/internal/cli/user_parser.go +++ b/internal/cli/user_parser.go @@ -522,7 +522,7 @@ func (p *Parser) parseAPIShowCommands() (*Command, error) { case TokenCurrent: return p.parseAPIShowCurrent() case TokenVar: - return p.parseShowVariable() + return p.parseAPIShowVariable() case TokenProvider: return p.parseAPIShowProviderCommands() case TokenModel: @@ -572,17 +572,17 @@ func (p *Parser) parseAPIShowCurrent() (*Command, error) { return NewCommand("api_show_current"), nil } -func (p *Parser) parseShowVariable() (*Command, error) { +func (p *Parser) parseAPIShowVariable() (*Command, error) { p.nextToken() // consume VAR - varName, err := p.parseIdentifier() + varName, err := p.parseQuotedString() if err != nil { return nil, err } + p.nextToken() - cmd := NewCommand("show_variable") + cmd := NewCommand("api_show_variable") cmd.Params["var_name"] = varName - p.nextToken() // Semicolon is optional if p.curToken.Type == TokenSemicolon { p.nextToken() diff --git a/internal/handler/system.go b/internal/handler/system.go index 8aa9d70371..7d25525b64 100644 --- a/internal/handler/system.go +++ b/internal/handler/system.go @@ -289,6 +289,41 @@ func (h *SystemHandler) SetVariable(c *gin.Context) { }) } +func (h *SystemHandler) ShowVariable(c *gin.Context) { + encodedVarName := c.Param("var_name") + + varName, err := common.DecodeFromBase64(encodedVarName) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": err.Error(), + }) + return + } + if varName == "" { + c.JSON(http.StatusOK, gin.H{ + "code": 400, + "message": "Var name is required", + }) + return + } + + variable, err := h.systemService.ShowVariable(varName) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": 500, + "message": err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "message": "SUCCESS", + "data": variable, + }) +} + // ListEnvironments handle list environments func (h *SystemHandler) ListEnvironments(c *gin.Context) { environments, err := h.systemService.ListEnvironments() diff --git a/internal/router/router.go b/internal/router/router.go index 91428a7842..d320ded31b 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -564,6 +564,7 @@ func (r *Router) Setup(engine *gin.Engine) { // Variables/Settings system.GET("/variables", r.systemHandler.ListVariables) system.PUT("/variables", r.systemHandler.SetVariable) + system.GET("/variables/:var_name", r.systemHandler.ShowVariable) // Environments system.GET("/environments", r.systemHandler.ListEnvironments) diff --git a/internal/service/system.go b/internal/service/system.go index cf82f7eb15..f6a4b894df 100644 --- a/internal/service/system.go +++ b/internal/service/system.go @@ -389,6 +389,24 @@ func (s *SystemService) ListAllVariables() ([]map[string]interface{}, error) { return common.FormatSystemSettings(settings), nil } +func (s *SystemService) ShowVariable(varName string) ([]map[string]interface{}, error) { + settings, err := s.systemSettingsDAO.GetByName(varName) + if err != nil { + return nil, err + } + + if len(settings) == 0 { + settings, err = s.systemSettingsDAO.GetByNamePrefix(varName) + if err != nil { + return nil, err + } + if len(settings) == 0 { + return nil, fmt.Errorf("can't get setting: %s", varName) + } + } + return common.FormatSystemSettings(settings), nil +} + // SetVariable set variable // Creates or updates a system setting // If the setting exists, updates it; otherwise creates a new one