From f7c9eddef553f534972ea0a9608984fc5d4d8098 Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Wed, 20 May 2026 08:41:27 -0700 Subject: [PATCH] Improve FCM service account loading and diagnostics. Support FCM_SERVICE_ACCOUNT_KEY_FILE, clearer JSON parse errors for common .env mistakes, stop logging credential contents. Co-authored-by: Cursor --- internal/config/config.go | 10 +++++++++- internal/services/notification/service.go | 7 ++++--- internal/web_server/handlers/notification_handler.go | 6 +++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index 87f28b0..4b24a08 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,6 +4,7 @@ import ( "Yimaru-Backend/internal/domain" customlogger "Yimaru-Backend/internal/logger" "errors" + "fmt" "log/slog" "os" "strconv" @@ -475,7 +476,14 @@ func (c *Config) loadEnv() error { } c.ResendSenderEmail = resendSenderEmail - c.FCMServiceAccountKey = os.Getenv("FCM_SERVICE_ACCOUNT_KEY") + c.FCMServiceAccountKey = strings.TrimSpace(os.Getenv("FCM_SERVICE_ACCOUNT_KEY")) + if fp := strings.TrimSpace(os.Getenv("FCM_SERVICE_ACCOUNT_KEY_FILE")); fp != "" { + raw, err := os.ReadFile(fp) + if err != nil { + return fmt.Errorf("read FCM_SERVICE_ACCOUNT_KEY_FILE %q: %w", fp, err) + } + c.FCMServiceAccountKey = strings.TrimSpace(string(raw)) + } // Vimeo configuration vimeoEnabled := os.Getenv("VIMEO_ENABLED") diff --git a/internal/services/notification/service.go b/internal/services/notification/service.go index 30750e3..e99b6ac 100644 --- a/internal/services/notification/service.go +++ b/internal/services/notification/service.go @@ -69,8 +69,9 @@ func New( config: cfg, } - mongoLogger.Info("FCM_SERVICE_ACCOUNT_KEY value at startup", - zap.String("fcm_service_account_key", cfg.FCMServiceAccountKey), + mongoLogger.Info("FCM credentials config at startup", + zap.Bool("fcm_credentials_configured", strings.TrimSpace(cfg.FCMServiceAccountKey) != ""), + zap.Int("fcm_service_account_json_len", len(strings.TrimSpace(cfg.FCMServiceAccountKey))), ) // Initialize FCM client if service account key is provided @@ -101,7 +102,7 @@ func (s *Service) initFCMClient() error { ProjectID string `json:"project_id"` } if err := json.Unmarshal([]byte(s.config.FCMServiceAccountKey), &sa); err != nil { - return fmt.Errorf("invalid FCM_SERVICE_ACCOUNT_KEY JSON: %w", err) + return fmt.Errorf("invalid FCM service account JSON: %w (hint: private_key must escape newlines as \\n; do not paste multiline JSON into .env unless quoted—use minified one line or FCM_SERVICE_ACCOUNT_KEY_FILE)", err) } if strings.TrimSpace(sa.ProjectID) == "" { return fmt.Errorf("FCM_SERVICE_ACCOUNT_KEY is missing project_id") diff --git a/internal/web_server/handlers/notification_handler.go b/internal/web_server/handlers/notification_handler.go index 7a61c39..96f3bc2 100644 --- a/internal/web_server/handlers/notification_handler.go +++ b/internal/web_server/handlers/notification_handler.go @@ -727,9 +727,9 @@ func (h *Handler) RegisterDeviceToken(c *fiber.Ctx) error { func (h *Handler) SendTestPushNotification(c *fiber.Ctx) error { title := c.FormValue("title", "Test Push Notification") message := c.FormValue("message", "This is a test push notification from Yimaru Backend") - h.mongoLoggerSvc.Info("FCM_SERVICE_ACCOUNT_KEY value during test-push call", - zap.String("fcm_service_account_key", h.Cfg.FCMServiceAccountKey), - zap.String("db_url", h.Cfg.DbUrl), + h.mongoLoggerSvc.Info("notification test-push diagnostics", + zap.Bool("fcm_credentials_configured", strings.TrimSpace(h.Cfg.FCMServiceAccountKey) != ""), + zap.Int("fcm_service_account_json_len", len(strings.TrimSpace(h.Cfg.FCMServiceAccountKey))), ) userID, ok := c.Locals("user_id").(int64)