Skip to content

Commit

Permalink
use new sherpadoc rename mechanism to remove some typename stuttering
Browse files Browse the repository at this point in the history
the stuttering was introduced to make the same type name declared in multiple
packages, and used in the admin sherpa api, unique. with sherpadoc's new
rename, we can make them unique when generating the api definition/docs, and
the Go code can use nicer names.
  • Loading branch information
mjl- committed Apr 19, 2024
1 parent 962575f commit ec967ef
Show file tree
Hide file tree
Showing 18 changed files with 73 additions and 83 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build0:
CGO_ENABLED=0 go build
CGO_ENABLED=0 go vet ./...
./gendoc.sh
(cd webadmin && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none -rename 'config Domain ConfigDomain' Admin) >webadmin/api.json
(cd webadmin && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none -rename 'config Domain ConfigDomain,dmarc Policy DMARCPolicy,mtasts MX STSMX,tlsrptdb Record TLSReportRecord,tlsrptdb SuppressAddress TLSRPTSuppressAddress' Admin) >webadmin/api.json
(cd webaccount && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >webaccount/api.json
(cd webmail && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Webmail) >webmail/api.json
./gents.sh webadmin/api.json webadmin/api.ts
Expand Down
4 changes: 2 additions & 2 deletions dmarc/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ func parseRecord(s string, checkRequired bool) (record *Record, isdmarc bool, re
// ../rfc/7489:1105
p.xerrorf("p= (policy) must be first tag")
}
r.Policy = DMARCPolicy(p.xtakelist("none", "quarantine", "reject"))
r.Policy = Policy(p.xtakelist("none", "quarantine", "reject"))
case "sp":
r.SubdomainPolicy = DMARCPolicy(p.xkeyword())
r.SubdomainPolicy = Policy(p.xkeyword())
// note: we check if the value is valid before returning.
case "rua":
r.AggregateReportAddresses = append(r.AggregateReportAddresses, p.xuri())
Expand Down
34 changes: 16 additions & 18 deletions dmarc/txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ import (
"strings"
)

// todo: DMARCPolicy should be named just Policy, but this is causing conflicting types in sherpadoc output. should somehow get the dmarc-prefix only in the sherpadoc.

// Policy as used in DMARC DNS record for "p=" or "sp=".
type DMARCPolicy string
type Policy string

// ../rfc/7489:1157

const (
PolicyEmpty DMARCPolicy = "" // Only for the optional Record.SubdomainPolicy.
PolicyNone DMARCPolicy = "none"
PolicyQuarantine DMARCPolicy = "quarantine"
PolicyReject DMARCPolicy = "reject"
PolicyEmpty Policy = "" // Only for the optional Record.SubdomainPolicy.
PolicyNone Policy = "none"
PolicyQuarantine Policy = "quarantine"
PolicyReject Policy = "reject"
)

// URI is a destination address for reporting.
Expand Down Expand Up @@ -55,17 +53,17 @@ const (
//
// v=DMARC1; p=reject; rua=mailto:[email protected]
type Record struct {
Version string // "v=DMARC1", fixed.
Policy DMARCPolicy // Required, for "p=".
SubdomainPolicy DMARCPolicy // Like policy but for subdomains. Optional, for "sp=".
AggregateReportAddresses []URI // Optional, for "rua=". Destination addresses for aggregate reports.
FailureReportAddresses []URI // Optional, for "ruf=". Destination addresses for failure reports.
ADKIM Align // Alignment: "r" (default) for relaxed or "s" for simple. For "adkim=".
ASPF Align // Alignment: "r" (default) for relaxed or "s" for simple. For "aspf=".
AggregateReportingInterval int // In seconds, default 86400. For "ri="
FailureReportingOptions []string // "0" (default), "1", "d", "s". For "fo=".
ReportingFormat []string // "afrf" (default). For "rf=".
Percentage int // Between 0 and 100, default 100. For "pct=". Policy applies randomly to this percentage of messages.
Version string // "v=DMARC1", fixed.
Policy Policy // Required, for "p=".
SubdomainPolicy Policy // Like policy but for subdomains. Optional, for "sp=".
AggregateReportAddresses []URI // Optional, for "rua=". Destination addresses for aggregate reports.
FailureReportAddresses []URI // Optional, for "ruf=". Destination addresses for failure reports.
ADKIM Align // Alignment: "r" (default) for relaxed or "s" for simple. For "adkim=".
ASPF Align // Alignment: "r" (default) for relaxed or "s" for simple. For "aspf=".
AggregateReportingInterval int // In seconds, default 86400. For "ri="
FailureReportingOptions []string // "0" (default), "1", "d", "s". For "fo=".
ReportingFormat []string // "afrf" (default). For "rf=".
Percentage int // Between 0 and 100, default 100. For "pct=". Policy applies randomly to this percentage of messages.
}

// DefaultRecord holds the defaults for a DMARC record.
Expand Down
2 changes: 1 addition & 1 deletion gentestdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Accounts:
mtastsPolicy := mtasts.Policy{
Version: "STSv1",
Mode: mtasts.ModeTesting,
MX: []mtasts.STSMX{
MX: []mtasts.MX{
{Domain: dns.Domain{ASCII: "mx1.example.com"}},
{Domain: dns.Domain{ASCII: "mx2.example.com"}},
{Domain: dns.Domain{ASCII: "backup-example.com"}, Wildcard: true},
Expand Down
6 changes: 3 additions & 3 deletions http/mtasts.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ func mtastsPolicyHandle(w http.ResponseWriter, r *http.Request) {
return
}

var mxs []mtasts.STSMX
var mxs []mtasts.MX
for _, s := range sts.MX {
var mx mtasts.STSMX
var mx mtasts.MX
if strings.HasPrefix(s, "*.") {
mx.Wildcard = true
s = s[2:]
Expand All @@ -60,7 +60,7 @@ func mtastsPolicyHandle(w http.ResponseWriter, r *http.Request) {
mxs = append(mxs, mx)
}
if len(mxs) == 0 {
mxs = []mtasts.STSMX{{Domain: mox.Conf.Static.HostnameDomain}}
mxs = []mtasts.MX{{Domain: mox.Conf.Static.HostnameDomain}}
}

policy := mtasts.Policy{
Expand Down
9 changes: 4 additions & 5 deletions mtasts/mtasts.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ const (
ModeNone Mode = "none" // In case MTA-STS is not or no longer implemented.
)

// STSMX is an allowlisted MX host name/pattern.
// todo: find a way to name this just STSMX without getting duplicate names for "MX" in the sherpa api.
type STSMX struct {
// MX is an allowlisted MX host name/pattern.
type MX struct {
// "*." wildcard, e.g. if a subdomain matches. A wildcard must match exactly one
// label. *.example.com matches mail.example.com, but not example.com, and not
// foor.bar.example.com.
Expand All @@ -88,7 +87,7 @@ type STSMX struct {

// LogString returns a loggable string representing the host, with both unicode
// and ascii version for IDNA domains.
func (s STSMX) LogString() string {
func (s MX) LogString() string {
pre := ""
if s.Wildcard {
pre = "*."
Expand All @@ -103,7 +102,7 @@ func (s STSMX) LogString() string {
type Policy struct {
Version string // "STSv1"
Mode Mode
MX []STSMX
MX []MX
MaxAgeSeconds int // How long this policy can be cached. Suggested values are in weeks or more.
Extensions []Pair
}
Expand Down
2 changes: 1 addition & 1 deletion mtasts/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func (p *parser) take(s string) bool {
}

// ../rfc/8461:469
func (p *parser) xmx() (mx STSMX) {
func (p *parser) xmx() (mx MX) {
if p.prefix("*.") {
mx.Wildcard = true
p.o += 2
Expand Down
8 changes: 4 additions & 4 deletions mtasts/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ max_age: 1296000
Policy{
Version: "STSv1",
Mode: ModeTesting,
MX: []STSMX{
MX: []MX{
{Domain: dns.Domain{ASCII: "mx1.example.com"}},
{Domain: dns.Domain{ASCII: "mx2.example.com"}},
{Domain: dns.Domain{ASCII: "mx.backup-example.com"}},
Expand All @@ -89,7 +89,7 @@ max_age: 1296000
Policy{
Version: "STSv1",
Mode: ModeEnforce,
MX: []STSMX{
MX: []MX{
{Wildcard: true, Domain: dns.Domain{ASCII: "example.com"}},
},
MaxAgeSeconds: 0,
Expand All @@ -99,7 +99,7 @@ max_age: 1296000
Policy{
Version: "STSv1",
Mode: ModeEnforce,
MX: []STSMX{
MX: []MX{
{Wildcard: true, Domain: dns.Domain{ASCII: "example.com"}},
},
MaxAgeSeconds: 1,
Expand Down Expand Up @@ -140,7 +140,7 @@ max_age: 1296000
policy := Policy{
Version: "STSv1",
Mode: ModeTesting,
MX: []STSMX{
MX: []MX{
{Domain: dns.Domain{ASCII: "mx1.example.com"}},
{Domain: dns.Domain{ASCII: "mx2.example.com"}},
{Domain: dns.Domain{ASCII: "mx.backup-example.com"}},
Expand Down
4 changes: 2 additions & 2 deletions mtastsdb/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestDB(t *testing.T) {
policy1 := mtasts.Policy{
Version: "STSv1",
Mode: mtasts.ModeTesting,
MX: []mtasts.STSMX{
MX: []mtasts.MX{
{Domain: dns.Domain{ASCII: "mx1.example.com"}},
{Domain: dns.Domain{ASCII: "mx2.example.com"}},
{Domain: dns.Domain{ASCII: "mx.backup-example.com"}},
Expand All @@ -71,7 +71,7 @@ func TestDB(t *testing.T) {
policy2 := mtasts.Policy{
Version: "STSv1",
Mode: mtasts.ModeEnforce,
MX: []mtasts.STSMX{
MX: []mtasts.MX{
{Domain: dns.Domain{ASCII: "mx1.example.com"}},
},
MaxAgeSeconds: 360000,
Expand Down
2 changes: 1 addition & 1 deletion mtastsdb/refresh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestRefresh(t *testing.T) {
policy := mtasts.Policy{
Version: "STSv1",
Mode: mode,
MX: []mtasts.STSMX{{Wildcard: false, Domain: mxd}},
MX: []mtasts.MX{{Wildcard: false, Domain: mxd}},
MaxAgeSeconds: maxAge,
Extensions: nil,
}
Expand Down
4 changes: 2 additions & 2 deletions tlsrptdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
)

var (
ReportDBTypes = []any{TLSReportRecord{}}
ReportDBTypes = []any{Record{}}
ReportDB *bstore.DB
mutex sync.Mutex

// Accessed directly by tlsrptsend.
ResultDBTypes = []any{TLSResult{}, TLSRPTSuppressAddress{}}
ResultDBTypes = []any{TLSResult{}, SuppressAddress{}}
ResultDB *bstore.DB
)

Expand Down
28 changes: 13 additions & 15 deletions tlsrptdb/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,10 @@ var (
}
)

// TLSReportRecord is a TLS report as a database record, including information
// Record is a TLS report as a database record, including information
// about the sender.
//
// todo: should be named just Record, but it would cause a sherpa type name conflict.
type TLSReportRecord struct {
ID int64 `bstore:"typename Record"`
type Record struct {
ID int64
Domain string `bstore:"index"` // Policy domain to which the TLS report applies. Unicode.
FromDomain string
MailFrom string
Expand Down Expand Up @@ -119,7 +117,7 @@ func AddReport(ctx context.Context, log mlog.Log, verifiedFromDomain dns.Domain,
metricSession.WithLabelValues(result).Add(float64(f.FailedSessionCount))
}

record := TLSReportRecord{0, d.Name(), verifiedFromDomain.Name(), mailFrom, d == mox.Conf.Static.HostnameDomain, *r}
record := Record{0, d.Name(), verifiedFromDomain.Name(), mailFrom, d == mox.Conf.Static.HostnameDomain, *r}
if err := tx.Insert(&record); err != nil {
return fmt.Errorf("inserting report for domain: %w", err)
}
Expand All @@ -133,41 +131,41 @@ func AddReport(ctx context.Context, log mlog.Log, verifiedFromDomain dns.Domain,
}

// Records returns all TLS reports in the database.
func Records(ctx context.Context) ([]TLSReportRecord, error) {
func Records(ctx context.Context) ([]Record, error) {
db, err := reportDB(ctx)
if err != nil {
return nil, err
}
return bstore.QueryDB[TLSReportRecord](ctx, db).List()
return bstore.QueryDB[Record](ctx, db).List()
}

// RecordID returns the report for the ID.
func RecordID(ctx context.Context, id int64) (TLSReportRecord, error) {
func RecordID(ctx context.Context, id int64) (Record, error) {
db, err := reportDB(ctx)
if err != nil {
return TLSReportRecord{}, err
return Record{}, err
}

e := TLSReportRecord{ID: id}
e := Record{ID: id}
err = db.Get(ctx, &e)
return e, err
}

// RecordsPeriodPolicyDomain returns the reports overlapping start and end, for the
// given policy domain. If policy domain is empty, records for all domains are
// returned.
func RecordsPeriodDomain(ctx context.Context, start, end time.Time, policyDomain dns.Domain) ([]TLSReportRecord, error) {
func RecordsPeriodDomain(ctx context.Context, start, end time.Time, policyDomain dns.Domain) ([]Record, error) {
db, err := reportDB(ctx)
if err != nil {
return nil, err
}

q := bstore.QueryDB[TLSReportRecord](ctx, db)
q := bstore.QueryDB[Record](ctx, db)
var zerodom dns.Domain
if policyDomain != zerodom {
q.FilterNonzero(TLSReportRecord{Domain: policyDomain.Name()})
q.FilterNonzero(Record{Domain: policyDomain.Name()})
}
q.FilterFn(func(r TLSReportRecord) bool {
q.FilterFn(func(r Record) bool {
dr := r.Report.DateRange
return !dr.Start.Before(start) && dr.Start.Before(end) || dr.End.After(start) && !dr.End.After(end)
})
Expand Down
18 changes: 8 additions & 10 deletions tlsrptdb/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,10 @@ type TLSResult struct {
Results []tlsrpt.Result
}

// todo: TLSRPTSuppressAddress should be named just SuppressAddress, but would clash with dmarcdb.SuppressAddress in sherpa api.

// TLSRPTSuppressAddress is a reporting address for which outgoing TLS reports
// SuppressAddress is a reporting address for which outgoing TLS reports
// will be suppressed for a period.
type TLSRPTSuppressAddress struct {
ID int64
type SuppressAddress struct {
ID int64 `bstore:"typename TLSRPTSuppressAddress"`
Inserted time.Time `bstore:"default now"`
ReportingAddress string `bstore:"unique"`
Until time.Time `bstore:"nonzero"`
Expand Down Expand Up @@ -205,7 +203,7 @@ func RemoveResultsRecipientDomain(ctx context.Context, recipientDomain dns.Domai
}

// SuppressAdd adds an address to the suppress list.
func SuppressAdd(ctx context.Context, ba *TLSRPTSuppressAddress) error {
func SuppressAdd(ctx context.Context, ba *SuppressAddress) error {
db, err := resultDB(ctx)
if err != nil {
return err
Expand All @@ -215,13 +213,13 @@ func SuppressAdd(ctx context.Context, ba *TLSRPTSuppressAddress) error {
}

// SuppressList returns all reporting addresses on the suppress list.
func SuppressList(ctx context.Context) ([]TLSRPTSuppressAddress, error) {
func SuppressList(ctx context.Context) ([]SuppressAddress, error) {
db, err := resultDB(ctx)
if err != nil {
return nil, err
}

return bstore.QueryDB[TLSRPTSuppressAddress](ctx, db).SortDesc("ID").List()
return bstore.QueryDB[SuppressAddress](ctx, db).SortDesc("ID").List()
}

// SuppressRemove removes a reporting address record from the suppress list.
Expand All @@ -231,7 +229,7 @@ func SuppressRemove(ctx context.Context, id int64) error {
return err
}

return db.Delete(ctx, &TLSRPTSuppressAddress{ID: id})
return db.Delete(ctx, &SuppressAddress{ID: id})
}

// SuppressUpdate updates the until field of a reporting address record.
Expand All @@ -241,7 +239,7 @@ func SuppressUpdate(ctx context.Context, id int64, until time.Time) error {
return err
}

ba := TLSRPTSuppressAddress{ID: id}
ba := SuppressAddress{ID: id}
err = db.Get(ctx, &ba)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions tlsrptsend/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,8 +577,8 @@ Period: %s - %s UTC
var queued bool
for _, rcpt := range recipients {
// If recipient is on suppression list, we won't queue the reporting message.
q := bstore.QueryDB[tlsrptdb.TLSRPTSuppressAddress](ctx, db)
q.FilterNonzero(tlsrptdb.TLSRPTSuppressAddress{ReportingAddress: rcpt.Address.Path().String()})
q := bstore.QueryDB[tlsrptdb.SuppressAddress](ctx, db)
q.FilterNonzero(tlsrptdb.SuppressAddress{ReportingAddress: rcpt.Address.Path().String()})
q.FilterGreater("Until", time.Now())
exists, err := q.Exists()
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions tlsrptsend/send_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,9 @@ func TestSendReports(t *testing.T) {
// Suppressed addresses don't get a report.
resolver.TXT["_smtp._tls.mailhost.xn--74h.example."] = []string{"v=TLSRPTv1; rua=mailto:[email protected],mailto:[email protected]; rua=mailto:[email protected]"}
db.Insert(ctxbg,
&tlsrptdb.TLSRPTSuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(-time.Minute)}, // Expired, so ignored.
&tlsrptdb.TLSRPTSuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(time.Minute)}, // Still valid.
&tlsrptdb.TLSRPTSuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(31 * 24 * time.Hour)}, // Still valid.
&tlsrptdb.SuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(-time.Minute)}, // Expired, so ignored.
&tlsrptdb.SuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(time.Minute)}, // Still valid.
&tlsrptdb.SuppressAddress{ReportingAddress: "[email protected]", Until: time.Now().Add(31 * 24 * time.Hour)}, // Still valid.
)
test(tlsResults, map[string][]tlsrpt.Report{
"[email protected]": {report1},
Expand Down
Loading

0 comments on commit ec967ef

Please sign in to comment.