diff --git a/api/internal/api/handlers.go b/api/internal/api/handlers.go
index 44ae071b..be99e170 100644
--- a/api/internal/api/handlers.go
+++ b/api/internal/api/handlers.go
@@ -1501,8 +1501,6 @@ func (h *Handler) AddRepository(c *gin.Context) {
// SyncRepository triggers a sync for a repository
func (h *Handler) SyncRepository(c *gin.Context) {
- // SECURITY FIX: Use request context for proper cancellation and timeout handling
- ctx := c.Request.Context()
repoIDStr := c.Param("id")
// Convert repo ID to int
diff --git a/api/internal/api/stubs.go b/api/internal/api/stubs.go
index fbd3ca5b..3820e77b 100644
--- a/api/internal/api/stubs.go
+++ b/api/internal/api/stubs.go
@@ -675,45 +675,53 @@ func (h *Handler) UpdateConfig(c *gin.Context) {
func (h *Handler) GetMetrics(c *gin.Context) {
ctx := c.Request.Context()
- // Get cluster nodes
- nodes, err := h.k8sClient.GetNodes(ctx)
- if err != nil {
- c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get cluster nodes"})
- return
- }
-
- // Count ready nodes
+ // Initialize default values
+ totalNodes := 0
readyNodes := 0
totalCPU := int64(0)
totalMemory := int64(0)
usedPods := 0
totalPods := 0
- for _, node := range nodes.Items {
- // Check if node is ready
- for _, condition := range node.Status.Conditions {
- if condition.Type == corev1.NodeReady && condition.Status == corev1.ConditionTrue {
- readyNodes++
- break
+ // Get cluster nodes (handle nil k8sClient gracefully)
+ if h.k8sClient != nil {
+ nodes, err := h.k8sClient.GetNodes(ctx)
+ if err != nil {
+ log.Printf("Failed to get cluster nodes: %v", err)
+ // Continue with default values instead of failing
+ } else {
+ totalNodes = len(nodes.Items)
+
+ // Count ready nodes and sum resources
+ for _, node := range nodes.Items {
+ // Check if node is ready
+ for _, condition := range node.Status.Conditions {
+ if condition.Type == corev1.NodeReady && condition.Status == corev1.ConditionTrue {
+ readyNodes++
+ break
+ }
+ }
+
+ // Sum up allocatable resources
+ if cpu, ok := node.Status.Allocatable[corev1.ResourceCPU]; ok {
+ totalCPU += cpu.MilliValue()
+ }
+ if memory, ok := node.Status.Allocatable[corev1.ResourceMemory]; ok {
+ totalMemory += memory.Value()
+ }
+ if pods, ok := node.Status.Allocatable[corev1.ResourcePods]; ok {
+ totalPods += int(pods.Value())
+ }
}
- }
- // Sum up allocatable resources
- if cpu, ok := node.Status.Allocatable[corev1.ResourceCPU]; ok {
- totalCPU += cpu.MilliValue()
- }
- if memory, ok := node.Status.Allocatable[corev1.ResourceMemory]; ok {
- totalMemory += memory.Value()
- }
- if pods, ok := node.Status.Allocatable[corev1.ResourcePods]; ok {
- totalPods += int(pods.Value())
+ // Get all pods to calculate resource usage
+ pods, err := h.k8sClient.GetPods(ctx, h.namespace)
+ if err == nil {
+ usedPods = len(pods.Items)
+ }
}
- }
-
- // Get all pods to calculate resource usage
- pods, err := h.k8sClient.GetPods(ctx, h.namespace)
- if err == nil {
- usedPods = len(pods.Items)
+ } else {
+ log.Printf("Warning: k8sClient is nil, returning metrics without cluster data")
}
// Get session counts from database
@@ -784,9 +792,9 @@ func (h *Handler) GetMetrics(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"cluster": gin.H{
"nodes": gin.H{
- "total": len(nodes.Items),
+ "total": totalNodes,
"ready": readyNodes,
- "notReady": len(nodes.Items) - readyNodes,
+ "notReady": totalNodes - readyNodes,
},
"sessions": gin.H{
"total": sessionCounts.Total,
diff --git a/api/internal/db/database.go b/api/internal/db/database.go
index 093f406a..7c3bf16a 100644
--- a/api/internal/db/database.go
+++ b/api/internal/db/database.go
@@ -75,6 +75,7 @@ import (
"regexp"
"strconv"
"strings"
+ "time"
"golang.org/x/crypto/bcrypt"
_ "github.com/lib/pq"
diff --git a/api/internal/handlers/notifications.go b/api/internal/handlers/notifications.go
index b209b738..942fa965 100644
--- a/api/internal/handlers/notifications.go
+++ b/api/internal/handlers/notifications.go
@@ -90,6 +90,7 @@ import (
"encoding/json"
"fmt"
"html/template"
+ "log"
"net/http"
"net/smtp"
"os"
diff --git a/ui/src/pages/admin/UserDetail.tsx b/ui/src/pages/admin/UserDetail.tsx
index a91ea4ae..5b48a2eb 100644
--- a/ui/src/pages/admin/UserDetail.tsx
+++ b/ui/src/pages/admin/UserDetail.tsx
@@ -284,7 +284,7 @@ export default function UserDetail() {
Role
-
+
@@ -292,7 +292,7 @@ export default function UserDetail() {
Provider
-
+