happyDomain/model/checker.go
Pierre-Olivier Mercier 7b094d919c Add CheckerHTMLReporter interface and Zonemaster HTML report
Introduces an optional CheckerHTMLReporter interface that checkers can
implement to expose a rich HTML document built from their stored Report
field.  The Zonemaster checker implements it, rendering results grouped
by module in collapsible accordions with color-coded severity badges.
2026-03-17 18:34:02 +07:00

156 lines
5.9 KiB
Go

// This file is part of the happyDomain (R) project.
// Copyright (c) 2020-2026 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 <contact@happydomain.org>.
//
// 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 <https://www.gnu.org/licenses/>.
package happydns
import (
"context"
"encoding/json"
"time"
)
// Auto-fill variable identifiers for checker option fields.
const (
// AutoFillDomainName fills the option with the fully qualified domain name
// of the domain being tested (e.g. "example.com.").
AutoFillDomainName = "domain_name"
// AutoFillSubdomain fills the option with the subdomain relative to the zone
// (e.g. "www" for "www.example.com." in zone "example.com."). Only
// applicable for service-scoped tests.
AutoFillSubdomain = "subdomain"
// AutoFillZone fills the option with the zone object. Only applicable
// for domain-scoped and service-scoped tests.
AutoFillZone = "zone"
// AutoFillServiceType fills the option with the service type identifier
// (e.g. "abstract.MatrixIM"). Only applicable for service-scoped tests.
AutoFillServiceType = "service_type"
// AutoFillService fills the option with the service object. Only applicable
// for service-scoped tests.
AutoFillService = "service"
)
const (
CheckResultStatusUnknown CheckResultStatus = iota
CheckResultStatusCritical
CheckResultStatusWarn
CheckResultStatusInfo
CheckResultStatusOK
)
type CheckResultStatus int
type CheckerOptions map[string]any
type Checker interface {
ID() string
Name() string
Availability() CheckerAvailability
Options() CheckerOptionsDocumentation
RunCheck(ctx context.Context, options CheckerOptions, meta map[string]string) (*CheckResult, error)
}
// CheckIntervalSpec describes the scheduling bounds for a checker.
type CheckIntervalSpec struct {
Min time.Duration `json:"min" swaggertype:"integer"`
Max time.Duration `json:"max" swaggertype:"integer"`
Default time.Duration `json:"default" swaggertype:"integer"`
}
// CheckerIntervalProvider is an optional interface checkers can implement
// to declare their preferred scheduling bounds. The scheduler enforces
// Min/Max; Default is used when creating a new schedule with no explicit interval.
type CheckerIntervalProvider interface {
CheckInterval() CheckIntervalSpec
}
// CheckerHTMLReporter is an optional interface checkers can implement
// to render their stored report as a full HTML document (for iframe embedding).
// Detect support with a type assertion: _, ok := checker.(CheckerHTMLReporter)
type CheckerHTMLReporter interface {
// GetHTMLReport generates an HTML document from the JSON-encoded report data
// stored in CheckResult.Report.
// The raw parameter contains the JSON bytes of the Report field as stored.
GetHTMLReport(raw json.RawMessage) (string, error)
}
type CheckerResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Availability CheckerAvailability `json:"availability"`
Options CheckerOptionsDocumentation `json:"options"`
Interval *CheckIntervalSpec `json:"interval"`
HasHTMLReport bool `json:"has_html_report,omitempty"`
}
type SetCheckerOptionsRequest struct {
Options CheckerOptions `json:"options"`
}
type CheckerOptionsPositional struct {
CheckName string
UserId *Identifier
DomainId *Identifier
ServiceId *Identifier
Options CheckerOptions
}
type CheckerAvailability struct {
ApplyToDomain bool `json:"applyToDomain,omitempty"`
ApplyToZone bool `json:"applyToZone,omitempty"`
ApplyToService bool `json:"applyToService,omitempty"`
LimitToProviders []string `json:"limitToProviders,omitempty"`
LimitToServices []string `json:"limitToServices,omitempty"`
}
type CheckerOptionsDocumentation struct {
RunOpts []CheckerOptionDocumentation `json:"runOpts,omitempty"`
ServiceOpts []CheckerOptionDocumentation `json:"serviceOpts,omitempty"`
DomainOpts []CheckerOptionDocumentation `json:"domainOpts,omitempty"`
UserOpts []CheckerOptionDocumentation `json:"userOpts,omitempty"`
AdminOpts []CheckerOptionDocumentation `json:"adminOpts,omitempty"`
}
type CheckerOptionDocumentation Field
// CheckerStatus represents the current status of a checker for a specific target,
// including whether it is enabled, its schedule, and the most recent result.
type CheckerStatus struct {
CheckerName string `json:"checker_name"`
NotDiscovered bool `json:"not_discovered,omitempty"`
Enabled bool `json:"enabled"`
Schedule *CheckerSchedule `json:"schedule,omitempty"`
LastResult *CheckResult `json:"last_result,omitempty"`
}
type CheckerUsecase interface {
BuildMergedCheckerOptions(string, *Identifier, *Identifier, *Identifier, CheckerOptions) (CheckerOptions, error)
GetStoredCheckerOptionsNoDefault(string, *Identifier, *Identifier, *Identifier) (CheckerOptions, error)
GetChecker(string) (Checker, error)
GetCheckerOptions(string, *Identifier, *Identifier, *Identifier) (*CheckerOptions, error)
ListCheckers() (*map[string]Checker, error)
OverwriteSomeCheckerOptions(string, *Identifier, *Identifier, *Identifier, CheckerOptions) error
SetCheckerOptions(string, *Identifier, *Identifier, *Identifier, CheckerOptions) error
}