diff --git a/backend/internal/job/api_key_expiry_job.go b/backend/internal/job/api_key_expiry_job.go index 6524089b..969b7c7e 100644 --- a/backend/internal/job/api_key_expiry_job.go +++ b/backend/internal/job/api_key_expiry_job.go @@ -37,12 +37,16 @@ func (j *ApiKeyEmailJobs) checkAndNotifyExpiringApiKeys(ctx context.Context) err } for _, key := range apiKeys { - if key.User.Email == nil { + if key.User.Email == nil || key.User.ID == "" { continue } err = j.apiKeyService.SendApiKeyExpiringSoonEmail(ctx, key) if err != nil { - slog.ErrorContext(ctx, "Failed to send expiring API key notification email", slog.String("key", key.ID), slog.Any("error", err)) + slog.ErrorContext(ctx, "Failed to send expiring API key notification email", + slog.String("key", key.ID), + slog.String("user", key.User.ID), + slog.Any("error", err), + ) } } return nil diff --git a/backend/internal/service/api_key_service.go b/backend/internal/service/api_key_service.go index 3c29d6e9..cb409ec5 100644 --- a/backend/internal/service/api_key_service.go +++ b/backend/internal/service/api_key_service.go @@ -3,6 +3,7 @@ package service import ( "context" "errors" + "fmt" "time" datatype "github.com/pocket-id/pocket-id/backend/internal/model/types" @@ -205,36 +206,33 @@ func (s *ApiKeyService) ListExpiringApiKeys(ctx context.Context, daysAhead int) } func (s *ApiKeyService) SendApiKeyExpiringSoonEmail(ctx context.Context, apiKey model.ApiKey) error { - user := apiKey.User - - if user.ID == "" { - if err := s.db.WithContext(ctx).First(&user, "id = ?", apiKey.UserID).Error; err != nil { - return err - } - } - - if user.Email == nil { + if apiKey.User.Email == nil { return &common.UserEmailNotSetError{} } err := SendEmail(ctx, s.emailService, email.Address{ - Name: user.FullName(), - Email: *user.Email, + Name: apiKey.User.FullName(), + Email: *apiKey.User.Email, }, ApiKeyExpiringSoonTemplate, &ApiKeyExpiringSoonTemplateData{ ApiKeyName: apiKey.Name, ExpiresAt: apiKey.ExpiresAt.ToTime(), - Name: user.FirstName, + Name: apiKey.User.FirstName, }) if err != nil { - return err + return fmt.Errorf("error sending notification email: %w", err) } // Mark the API key as having had an expiration email sent - return s.db.WithContext(ctx). + err = s.db.WithContext(ctx). Model(&model.ApiKey{}). Where("id = ?", apiKey.ID). Update("expiration_email_sent", true). Error + if err != nil { + return fmt.Errorf("error recording expiration sent email in database: %w", err) + } + + return nil } func (s *ApiKeyService) initStaticApiKeyUser(ctx context.Context) (user model.User, err error) { diff --git a/backend/internal/service/email_service.go b/backend/internal/service/email_service.go index 05affa5b..7dffa08c 100644 --- a/backend/internal/service/email_service.go +++ b/backend/internal/service/email_service.go @@ -150,7 +150,8 @@ func SendEmail[V any](ctx context.Context, srv *EmailService, toEmail email.Addr } // Send the email - if err := srv.sendEmailContent(client, toEmail, c); err != nil { + err = srv.sendEmailContent(client, toEmail, c) + if err != nil { return fmt.Errorf("send email content: %w", err) } diff --git a/backend/resources/email-templates/api-key-expiring-soon_html.tmpl b/backend/resources/email-templates/api-key-expiring-soon_html.tmpl index 8b52a5a0..b9b3bb5c 100644 --- a/backend/resources/email-templates/api-key-expiring-soon_html.tmpl +++ b/backend/resources/email-templates/api-key-expiring-soon_html.tmpl @@ -1 +1 @@ -{{define "root"}}
{{.AppName}}

{{.AppName}}

API Key Expiring Soon

Warning

Hello {{.Data.Name}},
This is a reminder that your API key {{.Data.APIKeyName}} will expire on {{.Data.ExpiresAt.Format "2006-01-02 15:04:05 MST"}}.

Please generate a new API key if you need continued access.

{{end}} \ No newline at end of file +{{define "root"}}
{{.AppName}}

{{.AppName}}

API Key Expiring Soon

Warning

Hello {{.Data.Name}},
This is a reminder that your API key {{.Data.ApiKeyName}} will expire on {{.Data.ExpiresAt.Format "2006-01-02 15:04:05 MST"}}.

Please generate a new API key if you need continued access.

{{end}} \ No newline at end of file diff --git a/backend/resources/email-templates/api-key-expiring-soon_text.tmpl b/backend/resources/email-templates/api-key-expiring-soon_text.tmpl index ae7ba74b..247969d5 100644 --- a/backend/resources/email-templates/api-key-expiring-soon_text.tmpl +++ b/backend/resources/email-templates/api-key-expiring-soon_text.tmpl @@ -6,6 +6,6 @@ API KEY EXPIRING SOON Warning Hello {{.Data.Name}}, -This is a reminder that your API key {{.Data.APIKeyName}} will expire on {{.Data.ExpiresAt.Format "2006-01-02 15:04:05 MST"}}. +This is a reminder that your API key {{.Data.ApiKeyName}} will expire on {{.Data.ExpiresAt.Format "2006-01-02 15:04:05 MST"}}. Please generate a new API key if you need continued access.{{end}} \ No newline at end of file diff --git a/email-templates/emails/api-key-expiring-soon.tsx b/email-templates/emails/api-key-expiring-soon.tsx index 6ddcc327..2a33987d 100644 --- a/email-templates/emails/api-key-expiring-soon.tsx +++ b/email-templates/emails/api-key-expiring-soon.tsx @@ -40,7 +40,7 @@ ApiKeyExpiringEmail.TemplateProps = { ...sharedTemplateProps, data: { name: "{{.Data.Name}}", - apiKeyName: "{{.Data.APIKeyName}}", + apiKeyName: "{{.Data.ApiKeyName}}", expiresAt: '{{.Data.ExpiresAt.Format "2006-01-02 15:04:05 MST"}}', }, };