Branding: bulk rename across 50+ files (Go, JS, CSS, HTML, YAML, JSON, shell scripts). Fix Helm chart description and git repo URLs. Fix test helper taglines. Admin surface: strip 14 gutted tabs (providers, models, personas, roles, knowledge, memory, tasks, health, routing, capabilities, channels, dashboard, usage, stats). Collapse to 4 categories: People, Workflows, System, Monitoring. Settings surface: strip 11 gutted tabs (models, personas, providers, roles, knowledge, memory, usage, workflows, tasks, data, gitkeys). Keep: general, appearance, profile, teams, connections, notifications. Team-admin surface: strip 5 gutted tabs (personas, providers, knowledge, tasks, usage). Keep: members, groups, connections, workflows, settings, activity. Components: delete chat-pane/ (13 files, 1938 lines) and notes-pane/ (10 files, 2381 lines). main.go: remove stale Health.Prune maintenance goroutine. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
79 lines
2.4 KiB
Go
79 lines
2.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"switchboard-core/notifications"
|
|
"switchboard-core/store"
|
|
)
|
|
|
|
// AdminEmailHandler handles admin SMTP configuration and test endpoints.
|
|
type AdminEmailHandler struct {
|
|
stores store.Stores
|
|
}
|
|
|
|
// NewAdminEmailHandler creates a new admin email handler.
|
|
func NewAdminEmailHandler(s store.Stores) *AdminEmailHandler {
|
|
return &AdminEmailHandler{stores: s}
|
|
}
|
|
|
|
// TestEmail sends a test email to the requesting admin's email address.
|
|
// POST /api/v1/admin/notifications/test-email
|
|
func (h *AdminEmailHandler) TestEmail(c *gin.Context) {
|
|
userID := getUserID(c)
|
|
if userID == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "authentication required"})
|
|
return
|
|
}
|
|
|
|
user, err := h.stores.Users.GetByID(c.Request.Context(), userID)
|
|
if err != nil || user == nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
|
|
return
|
|
}
|
|
if user.Email == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no email address configured for your account"})
|
|
return
|
|
}
|
|
|
|
// Load current SMTP config
|
|
cfg, err := notifications.LoadSMTPConfig(h.stores.GlobalConfig, nil)
|
|
if err != nil || cfg == nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "SMTP not configured: " + err.Error()})
|
|
return
|
|
}
|
|
|
|
transport := notifications.NewEmailTransport(*cfg)
|
|
if transport == nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "SMTP configuration is incomplete"})
|
|
return
|
|
}
|
|
|
|
// Get instance name
|
|
instanceName := "Switchboard Core"
|
|
if branding, err := h.stores.GlobalConfig.Get(context.Background(), "branding"); err == nil {
|
|
if name, ok := branding["instance_name"].(string); ok && name != "" {
|
|
instanceName = name
|
|
}
|
|
}
|
|
|
|
subject := "[" + instanceName + "] Test Email"
|
|
htmlBody := `<!DOCTYPE html>
|
|
<html><body style="font-family: sans-serif; padding: 20px;">
|
|
<h2 style="color: #4a8af4;">` + instanceName + `</h2>
|
|
<p>This is a test email from your Switchboard Core instance.</p>
|
|
<p>If you received this, your SMTP configuration is working correctly.</p>
|
|
</body></html>`
|
|
textBody := instanceName + " — Test Email\n\nThis is a test email. Your SMTP configuration is working correctly."
|
|
|
|
if err := transport.Send(c.Request.Context(), user.Email, subject, htmlBody, textBody); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "send failed: " + err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"ok": true, "sent_to": user.Email})
|
|
}
|