Create Api Key added

This commit is contained in:
Blomios
2026-01-11 23:08:03 +01:00
parent a64b10175e
commit 03ef8342e3
11 changed files with 461 additions and 83 deletions

View File

@ -1,7 +1,11 @@
package handlers
import (
"backend/models"
"crypto/rand"
"encoding/hex"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
@ -10,3 +14,52 @@ func (r *NodeHandler) LoginHandler(c *gin.Context) {
log.Println("trying to login")
r.Repo.LoginHandler(c)
}
func GenerateSecureKey() (string, error) {
bytes := make([]byte, 32) // 256 bits
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
func (r *NodeHandler) CreateApiKeyHandler(c *gin.Context) {
log.Println("trying to create key")
newApiKey, err := GenerateSecureKey()
if err != nil {
log.Printf("Generate API key error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "key creation error"})
return
}
var key models.CreateApiKeyResponse
key, err = r.Repo.CreateApiKeyHandler(c, newApiKey)
if err != nil {
log.Printf("CreateApiKeyHandler error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "insert new api key error"})
return
}
c.JSON(http.StatusOK, key)
}
func (h *NodeHandler) HandleRetrieveApiKeys(c *gin.Context) {
log.Println("All nodes retrieved request")
registeredNodes, err := h.Repo.RetriveNodeList()
if err != nil {
log.Printf("Request error on retrieving all nodes: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de récupérer la liste des nœuds"})
return
}
log.Printf("nb nodes: %v", len(registeredNodes))
c.JSON(http.StatusOK, registeredNodes)
}

View File

@ -38,6 +38,27 @@ func SeedAdmin(db *sqlx.DB) error {
return nil
}
func NodeAuthMiddleware(repo *repositories.NodeRepository) gin.HandlerFunc {
return func(c *gin.Context) {
key := c.GetHeader("X-Node-API-Key")
if key == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Clé API manquante"})
c.Abort()
return
}
isValid, err := repo.IsApiKeyValid(key)
if err != nil || !isValid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Clé API invalide"})
c.Abort()
return
}
c.Next()
}
}
func AuthRequired(c *gin.Context) {
session := sessions.Default(c)
userID := session.Get("user_id")
@ -92,15 +113,23 @@ func main() {
{
api.POST("/login", nodeHandler.LoginHandler)
api.POST("/register", nodeHandler.HandleRegisterNode)
api.POST("/registerService", nodeHandler.HandleRegisterService)
api.POST("/updateServiceStatus", nodeHandler.HandleUpdateServiceStatus)
protected := api.Group("/")
protected.Use(AuthRequired)
{
protected.DELETE("/deleteService", nodeHandler.HandleDeleteService)
protected.POST("/createApiKey", nodeHandler.CreateApiKeyHandler)
protected.GET("/retrieveNodeList", nodeHandler.HandleRetrieveNodeList)
protected.GET("/retrieveApiKeys", nodeHandler.HandleRetrieveApiKeys)
}
nodes := api.Group("/")
nodes.Use(NodeAuthMiddleware(nodeRepo))
{
nodes.POST("/register", nodeHandler.HandleRegisterNode)
nodes.POST("/registerService", nodeHandler.HandleRegisterService)
nodes.POST("/updateServiceStatus", nodeHandler.HandleUpdateServiceStatus)
}
}

View File

@ -0,0 +1,7 @@
CREATE TABLE node_api_keys (
id SERIAL PRIMARY KEY,
key_name VARCHAR(100),
key_value VARCHAR(64) UNIQUE NOT NULL,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@ -9,3 +9,13 @@ type LoginResponse struct {
Message string `json:"message"`
Role string `json:"role"`
}
type CreateApiKeyRequest struct {
KeyName string `json:"key_name"`
}
type CreateApiKeyResponse struct {
Id int `json:"id" db:"id"`
KeyName string `json:"key_name" db:"key_name"`
Key string `json:"key" db:"key_value"`
}

View File

@ -11,6 +11,29 @@ import (
"golang.org/x/crypto/bcrypt"
)
func (r *NodeRepository) IsApiKeyValid(key string) (bool, error) {
var exists bool
query := "SELECT exists(SELECT 1 FROM node_api_keys WHERE key_value=$1 AND is_active=true)"
err := r.DB.Get(&exists, query, key)
return exists, err
}
func (r *NodeRepository) CreateApiKeyHandler(c *gin.Context, newKey string) (models.CreateApiKeyResponse, error) {
var key models.CreateApiKeyResponse
var req models.CreateApiKeyRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Format invalide"})
return key, err
}
query := "INSERT INTO node_api_keys (key_value, key_name) VALUES ($1, $2) RETURNING id, key_name, key_value;"
err := r.DB.Get(&key, query, newKey, req.KeyName)
return key, err
}
func (r *NodeRepository) LoginHandler(c *gin.Context) {
var req models.LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {