fix: restore clients page functionality
Updated handleGetClients to return UI-compatible data format and implemented handleGetClient/handleUpdateClient endpoints.
This commit is contained in:
@@ -401,7 +401,114 @@ func (s *Server) handleGetClients(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
|
c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, SuccessResponse(clients))
|
|
||||||
|
type UIClient struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
LastUsed *time.Time `json:"last_used"`
|
||||||
|
RequestsCount int `json:"requests_count"`
|
||||||
|
TokensCount int `json:"tokens_count"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
RateLimitPerMinute int `json:"rate_limit_per_minute"`
|
||||||
|
}
|
||||||
|
|
||||||
|
uiClients := make([]UIClient, len(clients))
|
||||||
|
for i, cl := range clients {
|
||||||
|
status := "active"
|
||||||
|
if !cl.IsActive {
|
||||||
|
status = "disabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
name := ""
|
||||||
|
if cl.Name != nil {
|
||||||
|
name = *cl.Name
|
||||||
|
}
|
||||||
|
desc := ""
|
||||||
|
if cl.Description != nil {
|
||||||
|
desc = *cl.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get last used from tokens
|
||||||
|
var lastUsed *time.Time
|
||||||
|
_ = s.database.Get(&lastUsed, "SELECT MAX(last_used_at) FROM client_tokens WHERE client_id = ?", cl.ClientID)
|
||||||
|
|
||||||
|
uiClients[i] = UIClient{
|
||||||
|
ID: cl.ClientID,
|
||||||
|
Name: name,
|
||||||
|
Description: desc,
|
||||||
|
CreatedAt: cl.CreatedAt,
|
||||||
|
LastUsed: lastUsed,
|
||||||
|
RequestsCount: cl.TotalRequests,
|
||||||
|
TokensCount: cl.TotalTokens,
|
||||||
|
Status: status,
|
||||||
|
RateLimitPerMinute: cl.RateLimitPerMinute,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, SuccessResponse(uiClients))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) handleGetClient(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
var cl db.Client
|
||||||
|
err := s.database.Get(&cl, "SELECT * FROM clients WHERE client_id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusNotFound, ErrorResponse("Client not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name := ""
|
||||||
|
if cl.Name != nil {
|
||||||
|
name = *cl.Name
|
||||||
|
}
|
||||||
|
desc := ""
|
||||||
|
if cl.Description != nil {
|
||||||
|
desc = *cl.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, SuccessResponse(gin.H{
|
||||||
|
"id": cl.ClientID,
|
||||||
|
"name": name,
|
||||||
|
"description": desc,
|
||||||
|
"is_active": cl.IsActive,
|
||||||
|
"rate_limit_per_minute": cl.RateLimitPerMinute,
|
||||||
|
"created_at": cl.CreatedAt,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateClientRequest struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
IsActive bool `json:"is_active"`
|
||||||
|
RateLimitPerMinute *int `json:"rate_limit_per_minute"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) handleUpdateClient(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
var req UpdateClientRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, ErrorResponse("Invalid request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := s.database.Exec(`
|
||||||
|
UPDATE clients SET
|
||||||
|
name = ?,
|
||||||
|
description = ?,
|
||||||
|
is_active = ?,
|
||||||
|
rate_limit_per_minute = COALESCE(?, rate_limit_per_minute),
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE client_id = ?
|
||||||
|
`, req.Name, req.Description, req.IsActive, req.RateLimitPerMinute, id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "Client updated"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateClientRequest struct {
|
type CreateClientRequest struct {
|
||||||
@@ -676,7 +783,7 @@ func (s *Server) handleTestProvider(c *gin.Context) {
|
|||||||
|
|
||||||
// Prepare a simple test request
|
// Prepare a simple test request
|
||||||
testReq := &models.UnifiedRequest{
|
testReq := &models.UnifiedRequest{
|
||||||
Model: "gpt-4o-mini", // Default cheap test model for OpenAI
|
Model: "gpt-4o-mini", // Default cheap test model
|
||||||
Messages: []models.UnifiedMessage{
|
Messages: []models.UnifiedMessage{
|
||||||
{
|
{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ func (s *Server) setupRoutes() {
|
|||||||
|
|
||||||
admin.GET("/clients", s.handleGetClients)
|
admin.GET("/clients", s.handleGetClients)
|
||||||
admin.POST("/clients", s.handleCreateClient)
|
admin.POST("/clients", s.handleCreateClient)
|
||||||
|
admin.GET("/clients/:id", s.handleGetClient)
|
||||||
|
admin.PUT("/clients/:id", s.handleUpdateClient)
|
||||||
admin.DELETE("/clients/:id", s.handleDeleteClient)
|
admin.DELETE("/clients/:id", s.handleDeleteClient)
|
||||||
|
|
||||||
admin.GET("/clients/:id/tokens", s.handleGetClientTokens)
|
admin.GET("/clients/:id/tokens", s.handleGetClientTokens)
|
||||||
|
|||||||
Reference in New Issue
Block a user