diff --git a/internal/app/app.go b/internal/app/app.go index 0f13dca5..bd942828 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -246,7 +246,7 @@ func (app *App) initInsights() { func (app *App) initUsecases() { sessionService := sessionUC.NewService(app.store) authUserService := authuserUC.NewAuthUserUsecases(app.cfg, app.mailer, app.store, sessionService) - domainLogService := domainlogUC.NewDomainLogUsecases(app.store) + domainLogService := domainlogUC.NewService(app.store) providerService := providerUC.NewRestrictedProviderUsecases(app.cfg, app.store) serviceService := serviceUC.NewServiceUsecases() zoneService := zoneUC.NewZoneUsecases(app.store, serviceService) @@ -259,7 +259,7 @@ func (app *App) initUsecases() { app.usecases.zone = zoneService app.usecases.domainLog = domainLogService - domainService := domainUC.NewDomainUsecases(app.store, providerService.GetProviderUC, zoneService.GetZoneUC, providerService.DomainExistenceUC, domainLogService.CreateDomainLogUC) + domainService := domainUC.NewDomainUsecases(app.store, providerService.GetProviderUC, zoneService.GetZoneUC, providerService.DomainExistenceUC, domainLogService) app.usecases.domain = domainService app.usecases.zoneService = zoneServiceUC.NewZoneServiceUsecases(domainService.UpdateDomainUC, zoneService.CreateZoneUC, serviceService.ValidateServiceUC, app.store) @@ -270,7 +270,7 @@ func (app *App) initUsecases() { app.usecases.session = sessionService app.usecases.orchestrator = orchestrator.NewOrchestrator( - domainLogService.CreateDomainLogUC, + domainLogService, domainService.UpdateDomainUC, providerService.GetProviderUC, zoneService.ListRecordsUC, diff --git a/internal/usecase/domain/create_domain.go b/internal/usecase/domain/create_domain.go index 3ba9f126..09399163 100644 --- a/internal/usecase/domain/create_domain.go +++ b/internal/usecase/domain/create_domain.go @@ -31,12 +31,12 @@ import ( type CreateDomainUsecase struct { domainExistence *providerUC.DomainExistenceUsecase - domainLogAppender *domainLogUC.CreateDomainLogUsecase + domainLogAppender domainLogUC.DomainLogAppender getProvider *providerUC.GetProviderUsecase store DomainStorage } -func NewCreateDomainUsecase(store DomainStorage, getProvider *providerUC.GetProviderUsecase, domainExistence *providerUC.DomainExistenceUsecase, domainLogAppender *domainLogUC.CreateDomainLogUsecase) *CreateDomainUsecase { +func NewCreateDomainUsecase(store DomainStorage, getProvider *providerUC.GetProviderUsecase, domainExistence *providerUC.DomainExistenceUsecase, domainLogAppender domainLogUC.DomainLogAppender) *CreateDomainUsecase { return &CreateDomainUsecase{ domainExistence: domainExistence, domainLogAppender: domainLogAppender, @@ -69,7 +69,7 @@ func (uc *CreateDomainUsecase) Create(user *happydns.User, uz *happydns.Domain) // Add a log entry if uc.domainLogAppender != nil { - uc.domainLogAppender.Create(uz, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Domain name %s added.", uz.DomainName))) + uc.domainLogAppender.AppendDomainLog(uz, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Domain name %s added.", uz.DomainName))) } return nil diff --git a/internal/usecase/domain/factory.go b/internal/usecase/domain/factory.go index a1c8a8aa..74c7a079 100644 --- a/internal/usecase/domain/factory.go +++ b/internal/usecase/domain/factory.go @@ -41,7 +41,7 @@ func NewDomainUsecases( getProviderUC *providerUC.GetProviderUsecase, getZoneUC *zoneUC.GetZoneUsecase, domainExistenceUC *providerUC.DomainExistenceUsecase, - domainLogAppenderUC *domainLogUC.CreateDomainLogUsecase, + domainLogAppenderUC domainLogUC.DomainLogAppender, ) *Service { getDomainUC := NewGetDomainUsecase(store, getZoneUC) diff --git a/internal/usecase/domain/update_domain.go b/internal/usecase/domain/update_domain.go index bd62c25f..84183739 100644 --- a/internal/usecase/domain/update_domain.go +++ b/internal/usecase/domain/update_domain.go @@ -29,12 +29,12 @@ import ( ) type UpdateDomainUsecase struct { - domainLogAppender *domainLogUC.CreateDomainLogUsecase + domainLogAppender domainLogUC.DomainLogAppender getDomain *GetDomainUsecase store DomainStorage } -func NewUpdateDomainUsecase(store DomainStorage, getDomain *GetDomainUsecase, domainLogAppender *domainLogUC.CreateDomainLogUsecase) *UpdateDomainUsecase { +func NewUpdateDomainUsecase(store DomainStorage, getDomain *GetDomainUsecase, domainLogAppender domainLogUC.DomainLogAppender) *UpdateDomainUsecase { return &UpdateDomainUsecase{ domainLogAppender: domainLogAppender, getDomain: getDomain, @@ -65,7 +65,7 @@ func (uc *UpdateDomainUsecase) Update(domainid happydns.Identifier, user *happyd // Add a log entry if uc.domainLogAppender != nil { - uc.domainLogAppender.Create(domain, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Domain name %s properties changed.", domain.DomainName))) + uc.domainLogAppender.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Domain name %s properties changed.", domain.DomainName))) } return nil diff --git a/internal/usecase/domain_log/create_domain_log.go b/internal/usecase/domain_log/create_domain_log.go deleted file mode 100644 index d3dbc0db..00000000 --- a/internal/usecase/domain_log/create_domain_log.go +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of the happyDomain (R) project. -// Copyright (c) 2020-2025 happyDomain -// Authors: Pierre-Olivier Mercier, et al. -// -// This program is offered under a commercial and under the AGPL license. -// For commercial licensing, contact us at . -// -// For AGPL licensing: -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package domainlog - -import ( - "git.happydns.org/happyDomain/model" -) - -type CreateDomainLogUsecase struct { - store DomainLogStorage -} - -func NewCreateDomainLogUsecase(store DomainLogStorage) *CreateDomainLogUsecase { - return &CreateDomainLogUsecase{ - store: store, - } -} - -func (uc *CreateDomainLogUsecase) Create(domain *happydns.Domain, log *happydns.DomainLog) error { - return uc.store.CreateDomainLog(domain, log) -} diff --git a/internal/usecase/domain_log/delete_domain_log.go b/internal/usecase/domain_log/delete_domain_log.go deleted file mode 100644 index f094a860..00000000 --- a/internal/usecase/domain_log/delete_domain_log.go +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of the happyDomain (R) project. -// Copyright (c) 2020-2025 happyDomain -// Authors: Pierre-Olivier Mercier, et al. -// -// This program is offered under a commercial and under the AGPL license. -// For commercial licensing, contact us at . -// -// For AGPL licensing: -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package domainlog - -import ( - "git.happydns.org/happyDomain/model" -) - -type DeleteDomainLogUsecase struct { - store DomainLogStorage -} - -func NewDeleteDomainLogUsecase(store DomainLogStorage) *DeleteDomainLogUsecase { - return &DeleteDomainLogUsecase{ - store: store, - } -} - -func (uc *DeleteDomainLogUsecase) Delete(domain *happydns.Domain, log *happydns.DomainLog) error { - return uc.store.DeleteDomainLog(domain, log) -} diff --git a/internal/usecase/domain_log/list_domain_logs.go b/internal/usecase/domain_log/domainlog.go similarity index 57% rename from internal/usecase/domain_log/list_domain_logs.go rename to internal/usecase/domain_log/domainlog.go index a8d69776..5248d4ec 100644 --- a/internal/usecase/domain_log/list_domain_logs.go +++ b/internal/usecase/domain_log/domainlog.go @@ -28,18 +28,30 @@ import ( "git.happydns.org/happyDomain/model" ) -type ListDomainLogsUsecase struct { +// DomainLogAppender is a minimal interface for appending domain logs. +// Used by orchestrator to decouple from the full Service. +type DomainLogAppender interface { + AppendDomainLog(domain *happydns.Domain, entry *happydns.DomainLog) error +} + +type Service struct { store DomainLogStorage } -func NewListDomainLogsUsecase(store DomainLogStorage) *ListDomainLogsUsecase { - return &ListDomainLogsUsecase{ +func NewService(store DomainLogStorage) *Service { + return &Service{ store: store, } } -func (uc *ListDomainLogsUsecase) List(domain *happydns.Domain) ([]*happydns.DomainLog, error) { - logs, err := uc.store.ListDomainLogs(domain) +// AppendDomainLog creates a new domain log entry. +func (s *Service) AppendDomainLog(domain *happydns.Domain, entry *happydns.DomainLog) error { + return s.store.CreateDomainLog(domain, entry) +} + +// ListDomainLogs retrieves all logs for a domain, sorted by date (newest first). +func (s *Service) ListDomainLogs(domain *happydns.Domain) ([]*happydns.DomainLog, error) { + logs, err := s.store.ListDomainLogs(domain) if err != nil { return nil, happydns.InternalError{ Err: fmt.Errorf("unable to retrieve logs for domain %q (did=%s): %w", domain.DomainName, domain.Id.String(), err), @@ -54,3 +66,13 @@ func (uc *ListDomainLogsUsecase) List(domain *happydns.Domain) ([]*happydns.Doma return logs, nil } + +// UpdateDomainLog updates an existing domain log entry. +func (s *Service) UpdateDomainLog(domain *happydns.Domain, log *happydns.DomainLog) error { + return s.store.UpdateDomainLog(domain, log) +} + +// DeleteDomainLog removes a domain log entry. +func (s *Service) DeleteDomainLog(domain *happydns.Domain, log *happydns.DomainLog) error { + return s.store.DeleteDomainLog(domain, log) +} diff --git a/internal/usecase/domain_log/factory.go b/internal/usecase/domain_log/factory.go deleted file mode 100644 index a549d9d5..00000000 --- a/internal/usecase/domain_log/factory.go +++ /dev/null @@ -1,52 +0,0 @@ -// This file is part of the happyDomain (R) project. -// Copyright (c) 2020-2025 happyDomain -// Authors: Pierre-Olivier Mercier, et al. -// -// This program is offered under a commercial and under the AGPL license. -// For commercial licensing, contact us at . -// -// For AGPL licensing: -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package domainlog - -import ( - "git.happydns.org/happyDomain/model" -) - -type Service struct { - CreateDomainLogUC *CreateDomainLogUsecase - DeleteDomainLogUC *DeleteDomainLogUsecase - ListDomainLogsUC *ListDomainLogsUsecase - UpdateDomainLogUC *UpdateDomainLogUsecase -} - -func NewDomainLogUsecases( - store DomainLogStorage, -) *Service { - return &Service{ - CreateDomainLogUC: NewCreateDomainLogUsecase(store), - DeleteDomainLogUC: NewDeleteDomainLogUsecase(store), - ListDomainLogsUC: NewListDomainLogsUsecase(store), - UpdateDomainLogUC: NewUpdateDomainLogUsecase(store), - } -} - -func (s *Service) AppendDomainLog(domain *happydns.Domain, entry *happydns.DomainLog) error { - return s.CreateDomainLogUC.Create(domain, entry) -} - -func (s *Service) ListDomainLogs(domain *happydns.Domain) ([]*happydns.DomainLog, error) { - return s.ListDomainLogsUC.List(domain) -} diff --git a/internal/usecase/domain_log/domain_log_storage.go b/internal/usecase/domain_log/storage.go similarity index 100% rename from internal/usecase/domain_log/domain_log_storage.go rename to internal/usecase/domain_log/storage.go diff --git a/internal/usecase/domain_log/update_domain_log.go b/internal/usecase/domain_log/update_domain_log.go deleted file mode 100644 index fd5a84d9..00000000 --- a/internal/usecase/domain_log/update_domain_log.go +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of the happyDomain (R) project. -// Copyright (c) 2020-2025 happyDomain -// Authors: Pierre-Olivier Mercier, et al. -// -// This program is offered under a commercial and under the AGPL license. -// For commercial licensing, contact us at . -// -// For AGPL licensing: -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package domainlog - -import ( - "git.happydns.org/happyDomain/model" -) - -type UpdateDomainLogUsecase struct { - store DomainLogStorage -} - -func NewUpdateDomainLogUsecase(store DomainLogStorage) *UpdateDomainLogUsecase { - return &UpdateDomainLogUsecase{ - store: store, - } -} - -func (uc *UpdateDomainLogUsecase) Update(domain *happydns.Domain, log *happydns.DomainLog) error { - return uc.store.UpdateDomainLog(domain, log) -} diff --git a/internal/usecase/orchestrator/factory.go b/internal/usecase/orchestrator/factory.go index cb108257..4da87c6d 100644 --- a/internal/usecase/orchestrator/factory.go +++ b/internal/usecase/orchestrator/factory.go @@ -35,7 +35,7 @@ type Orchestrator struct { } func NewOrchestrator( - appendDomainLog *domainlogUC.CreateDomainLogUsecase, + appendDomainLog domainlogUC.DomainLogAppender, domainUpdater *domainUC.UpdateDomainUsecase, getProvider *providerUC.GetProviderUsecase, listRecords *zoneUC.ListRecordsUsecase, diff --git a/internal/usecase/orchestrator/remote_zone_retriever.go b/internal/usecase/orchestrator/remote_zone_retriever.go index 22b8c141..4f40ceef 100644 --- a/internal/usecase/orchestrator/remote_zone_retriever.go +++ b/internal/usecase/orchestrator/remote_zone_retriever.go @@ -30,14 +30,14 @@ import ( ) type RemoteZoneImporterUsecase struct { - appendDomainLog *domainlogUC.CreateDomainLogUsecase + appendDomainLog domainlogUC.DomainLogAppender getProvider *providerUC.GetProviderUsecase zoneImporter *ZoneImporterUsecase zoneRetriever *providerUC.ZoneRetrieverUsecase } func NewRemoteZoneImporterUsecase( - appendDomainLog *domainlogUC.CreateDomainLogUsecase, + appendDomainLog domainlogUC.DomainLogAppender, getProvider *providerUC.GetProviderUsecase, zoneImporter *ZoneImporterUsecase, zoneRetriever *providerUC.ZoneRetrieverUsecase, @@ -68,7 +68,7 @@ func (uc *RemoteZoneImporterUsecase) Import(user *happydns.User, domain *happydn } if uc.appendDomainLog != nil { - uc.appendDomainLog.Create(domain, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Zone imported from provider API: %s", myZone.Id.String()))) + uc.appendDomainLog.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_INFO, fmt.Sprintf("Zone imported from provider API: %s", myZone.Id.String()))) } return myZone, nil diff --git a/internal/usecase/orchestrator/zone_correction_applier.go b/internal/usecase/orchestrator/zone_correction_applier.go index 0f5ecc6b..952a2b69 100644 --- a/internal/usecase/orchestrator/zone_correction_applier.go +++ b/internal/usecase/orchestrator/zone_correction_applier.go @@ -35,7 +35,7 @@ import ( ) type ZoneCorrectionApplierUsecase struct { - appendDomainLog *domainlogUC.CreateDomainLogUsecase + appendDomainLog domainlogUC.DomainLogAppender domainUpdater *domainUC.UpdateDomainUsecase getProvider *providerUC.GetProviderUsecase listRecords *zoneUC.ListRecordsUsecase @@ -45,7 +45,7 @@ type ZoneCorrectionApplierUsecase struct { } func NewZoneCorrectionApplierUsecase( - appendDomainLog *domainlogUC.CreateDomainLogUsecase, + appendDomainLog domainlogUC.DomainLogAppender, domainUpdater *domainUC.UpdateDomainUsecase, getProvider *providerUC.GetProviderUsecase, listRecords *zoneUC.ListRecordsUsecase, @@ -95,7 +95,7 @@ corrections: if err != nil { log.Printf("%s: unable to apply correction: %s", domain.DomainName, err.Error()) - uc.appendDomainLog.Create(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed record update (%s): %s", cr.Msg, err.Error()))) + uc.appendDomainLog.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed record update (%s): %s", cr.Msg, err.Error()))) errs = errors.Join(errs, fmt.Errorf("%s: %w", cr.Msg, err)) // Stop the zone update if we didn't change it yet if i == 0 { @@ -110,14 +110,14 @@ corrections: } if errs != nil { - uc.appendDomainLog.Create(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed zone publishing (%s): %d corrections were not applied due to errors.", zone.Id.String(), nbcorrections))) + uc.appendDomainLog.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed zone publishing (%s): %d corrections were not applied due to errors.", zone.Id.String(), nbcorrections))) return nil, happydns.ValidationError{Msg: fmt.Sprintf("unable to update the zone: %s", errs.Error())} } else if len(form.WantedCorrections) > 0 { - uc.appendDomainLog.Create(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed zone publishing (%s): %d corrections were not applied.", zone.Id.String(), nbcorrections))) + uc.appendDomainLog.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_ERR, fmt.Sprintf("Failed zone publishing (%s): %d corrections were not applied.", zone.Id.String(), nbcorrections))) return nil, happydns.ValidationError{Msg: fmt.Sprintf("unable to perform the following changes: %s", form.WantedCorrections)} } - uc.appendDomainLog.Create(domain, happydns.NewDomainLog(user, happydns.LOG_ACK, fmt.Sprintf("Zone published (%s), %d corrections applied with success", zone.Id.String(), nbcorrections))) + uc.appendDomainLog.AppendDomainLog(domain, happydns.NewDomainLog(user, happydns.LOG_ACK, fmt.Sprintf("Zone published (%s), %d corrections applied with success", zone.Id.String(), nbcorrections))) // Create a new zone in history for futher updates newZone := zone.DerivateNew()