its a bit broken
This commit is contained in:
@@ -10,75 +10,115 @@ import (
|
||||
"jiggablend/pkg/types"
|
||||
)
|
||||
|
||||
// handleGenerateRegistrationToken generates a new registration token
|
||||
func (s *Server) handleGenerateRegistrationToken(w http.ResponseWriter, r *http.Request) {
|
||||
// handleGenerateRunnerAPIKey generates a new runner API key
|
||||
func (s *Server) handleGenerateRunnerAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
userID, err := getUserID(r)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Default expiration: 24 hours
|
||||
expiresIn := 24 * time.Hour
|
||||
|
||||
var req struct {
|
||||
ExpiresInHours int `json:"expires_in_hours,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Scope string `json:"scope,omitempty"` // 'manager' or 'user'
|
||||
}
|
||||
if r.Body != nil && r.ContentLength > 0 {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err == nil {
|
||||
if req.ExpiresInHours == 0 {
|
||||
// 0 hours means infinite expiration
|
||||
expiresIn = 0
|
||||
} else if req.ExpiresInHours > 0 {
|
||||
expiresIn = time.Duration(req.ExpiresInHours) * time.Hour
|
||||
}
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: expected valid JSON - %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
token, err := s.secrets.GenerateRegistrationToken(userID, expiresIn)
|
||||
if req.Name == "" {
|
||||
s.respondError(w, http.StatusBadRequest, "API key name is required")
|
||||
return
|
||||
}
|
||||
|
||||
// Default scope to 'user' if not specified
|
||||
scope := req.Scope
|
||||
if scope == "" {
|
||||
scope = "user"
|
||||
}
|
||||
if scope != "manager" && scope != "user" {
|
||||
s.respondError(w, http.StatusBadRequest, "Scope must be 'manager' or 'user'")
|
||||
return
|
||||
}
|
||||
|
||||
keyInfo, err := s.secrets.GenerateRunnerAPIKey(userID, req.Name, req.Description, scope)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to generate token: %v", err))
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to generate API key: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
response := map[string]interface{}{
|
||||
"token": token,
|
||||
}
|
||||
if expiresIn == 0 {
|
||||
response["expires_in"] = "infinite"
|
||||
response["expires_at"] = nil
|
||||
} else {
|
||||
response["expires_in"] = expiresIn.String()
|
||||
response["expires_at"] = time.Now().Add(expiresIn)
|
||||
"id": keyInfo.ID,
|
||||
"key": keyInfo.Key,
|
||||
"name": keyInfo.Name,
|
||||
"description": keyInfo.Description,
|
||||
"is_active": keyInfo.IsActive,
|
||||
"created_at": keyInfo.CreatedAt,
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusCreated, response)
|
||||
}
|
||||
|
||||
// handleListRegistrationTokens lists all registration tokens
|
||||
func (s *Server) handleListRegistrationTokens(w http.ResponseWriter, r *http.Request) {
|
||||
tokens, err := s.secrets.ListRegistrationTokens()
|
||||
// handleListRunnerAPIKeys lists all runner API keys
|
||||
func (s *Server) handleListRunnerAPIKeys(w http.ResponseWriter, r *http.Request) {
|
||||
keys, err := s.secrets.ListRunnerAPIKeys()
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list tokens: %v", err))
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list API keys: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusOK, tokens)
|
||||
// Convert to response format (hide sensitive hash data)
|
||||
var response []map[string]interface{}
|
||||
for _, key := range keys {
|
||||
item := map[string]interface{}{
|
||||
"id": key.ID,
|
||||
"key_prefix": key.Key, // Only show prefix, not full key
|
||||
"name": key.Name,
|
||||
"is_active": key.IsActive,
|
||||
"created_at": key.CreatedAt,
|
||||
"created_by": key.CreatedBy,
|
||||
}
|
||||
if key.Description != nil {
|
||||
item["description"] = *key.Description
|
||||
}
|
||||
response = append(response, item)
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// handleRevokeRegistrationToken revokes a registration token
|
||||
func (s *Server) handleRevokeRegistrationToken(w http.ResponseWriter, r *http.Request) {
|
||||
tokenID, err := parseID(r, "id")
|
||||
// handleRevokeRunnerAPIKey revokes a runner API key
|
||||
func (s *Server) handleRevokeRunnerAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
keyID, err := parseID(r, "id")
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.secrets.RevokeRegistrationToken(tokenID); err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to revoke token: %v", err))
|
||||
if err := s.secrets.RevokeRunnerAPIKey(keyID); err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to revoke API key: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusOK, map[string]string{"message": "Token revoked"})
|
||||
s.respondJSON(w, http.StatusOK, map[string]string{"message": "API key revoked"})
|
||||
}
|
||||
|
||||
// handleDeleteRunnerAPIKey deletes a runner API key
|
||||
func (s *Server) handleDeleteRunnerAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
keyID, err := parseID(r, "id")
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.secrets.DeleteRunnerAPIKey(keyID); err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete API key: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
s.respondJSON(w, http.StatusOK, map[string]string{"message": "API key deleted"})
|
||||
}
|
||||
|
||||
// handleVerifyRunner manually verifies a runner
|
||||
@@ -136,8 +176,8 @@ func (s *Server) handleDeleteRunner(w http.ResponseWriter, r *http.Request) {
|
||||
// handleListRunnersAdmin lists all runners with admin details
|
||||
func (s *Server) handleListRunnersAdmin(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := s.db.Query(
|
||||
`SELECT id, name, hostname, status, last_heartbeat, capabilities,
|
||||
registration_token, verified, priority, created_at
|
||||
`SELECT id, name, hostname, status, last_heartbeat, capabilities,
|
||||
api_key_id, api_key_scope, priority, created_at
|
||||
FROM runners ORDER BY created_at DESC`,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -149,13 +189,13 @@ func (s *Server) handleListRunnersAdmin(w http.ResponseWriter, r *http.Request)
|
||||
runners := []map[string]interface{}{}
|
||||
for rows.Next() {
|
||||
var runner types.Runner
|
||||
var registrationToken sql.NullString
|
||||
var verified bool
|
||||
var apiKeyID sql.NullInt64
|
||||
var apiKeyScope string
|
||||
|
||||
err := rows.Scan(
|
||||
&runner.ID, &runner.Name, &runner.Hostname,
|
||||
&runner.Status, &runner.LastHeartbeat, &runner.Capabilities,
|
||||
®istrationToken, &verified, &runner.Priority, &runner.CreatedAt,
|
||||
&apiKeyID, &apiKeyScope, &runner.Priority, &runner.CreatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
s.respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to scan runner: %v", err))
|
||||
@@ -163,16 +203,16 @@ func (s *Server) handleListRunnersAdmin(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
runners = append(runners, map[string]interface{}{
|
||||
"id": runner.ID,
|
||||
"name": runner.Name,
|
||||
"hostname": runner.Hostname,
|
||||
"status": runner.Status,
|
||||
"last_heartbeat": runner.LastHeartbeat,
|
||||
"capabilities": runner.Capabilities,
|
||||
"registration_token": registrationToken.String,
|
||||
"verified": verified,
|
||||
"priority": runner.Priority,
|
||||
"created_at": runner.CreatedAt,
|
||||
"id": runner.ID,
|
||||
"name": runner.Name,
|
||||
"hostname": runner.Hostname,
|
||||
"status": runner.Status,
|
||||
"last_heartbeat": runner.LastHeartbeat,
|
||||
"capabilities": runner.Capabilities,
|
||||
"api_key_id": apiKeyID.Int64,
|
||||
"api_key_scope": apiKeyScope,
|
||||
"priority": runner.Priority,
|
||||
"created_at": runner.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -335,7 +375,7 @@ func (s *Server) handleSetRegistrationEnabled(w http.ResponseWriter, r *http.Req
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, "Invalid request body")
|
||||
s.respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: expected valid JSON - %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -359,7 +399,7 @@ func (s *Server) handleSetUserAdminStatus(w http.ResponseWriter, r *http.Request
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
s.respondError(w, http.StatusBadRequest, "Invalid request body")
|
||||
s.respondError(w, http.StatusBadRequest, fmt.Sprintf("Invalid request body: expected valid JSON - %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user