Files
pocket-id/backend/internal/job/api_key_expiry_job.go
T

74 lines
2.1 KiB
Go

package job
import (
"context"
"fmt"
"log/slog"
"github.com/go-co-op/gocron/v2"
"github.com/pocket-id/pocket-id/backend/internal/apikey"
"github.com/pocket-id/pocket-id/backend/internal/service"
"github.com/pocket-id/pocket-id/backend/internal/utils/email"
)
type ApiKeyEmailJobs struct {
apiKeyModule *apikey.Module
appConfigService *service.AppConfigService
emailService *service.EmailService
}
func (s *Scheduler) RegisterApiKeyExpiryJob(ctx context.Context, apiKeyModule *apikey.Module, appConfigService *service.AppConfigService, emailService *service.EmailService) error {
jobs := &ApiKeyEmailJobs{
apiKeyModule: apiKeyModule,
appConfigService: appConfigService,
emailService: emailService,
}
// Send every day at midnight
return s.RegisterJob(ctx, "ExpiredApiKeyEmailJob", gocron.CronJob("0 0 * * *", false), jobs.checkAndNotifyExpiringApiKeys, service.RegisterJobOpts{})
}
func (j *ApiKeyEmailJobs) checkAndNotifyExpiringApiKeys(ctx context.Context) error {
// Skip if the feature is disabled
if !j.appConfigService.GetDbConfig().EmailApiKeyExpirationEnabled.IsTrue() {
return nil
}
apiKeys, err := j.apiKeyModule.ListExpiringApiKeys(ctx, 7)
if err != nil {
return fmt.Errorf("failed to list expiring API keys: %w", err)
}
for _, key := range apiKeys {
if key.User.Email == nil {
continue
}
err = service.SendEmail(ctx, j.emailService, email.Address{
Name: key.User.FullName(),
Email: *key.User.Email,
}, service.ApiKeyExpiringSoonTemplate, &service.ApiKeyExpiringSoonTemplateData{
Name: key.User.FirstName,
ApiKeyName: key.Name,
ExpiresAt: key.ExpiresAt.ToTime(),
})
if err != nil {
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),
)
continue
}
if err = j.apiKeyModule.MarkExpirationEmailSent(ctx, key.ID); err != nil {
slog.ErrorContext(ctx, "Failed to record that the expiration email was sent",
slog.String("key", key.ID),
slog.Any("error", err),
)
}
}
return nil
}