Add Migadu domain admin with shared lists, compaction, and safer apply.
Build the Go API and React UI for managing domain denylist/allowlist/recipient deny and spam settings, plus shared lists that import/apply across domains with wildcard compaction, entry verification, and Migadu-friendly list encoding (including per-domain recipient filtering and rejection bisect on apply).
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package lists
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCompact(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
input: nil,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "exact duplicates case insensitive",
|
||||
input: []string{"Lisa@Simpsons.com", "lisa@simpsons.com", " LISA@SIMPSONS.COM "},
|
||||
want: []string{"lisa@simpsons.com"},
|
||||
},
|
||||
{
|
||||
name: "wildcard covers specific",
|
||||
input: []string{"lisa@simpsons.com", "*@simpsons.com"},
|
||||
want: []string{"*@simpsons.com"},
|
||||
},
|
||||
{
|
||||
name: "specific dropped when wildcard present first",
|
||||
input: []string{"*@simpsons.com", "lisa@simpsons.com", "homer@simpsons.com"},
|
||||
want: []string{"*@simpsons.com"},
|
||||
},
|
||||
{
|
||||
name: "distinct locals kept",
|
||||
input: []string{"lisa@simpsons.com", "homer@simpsons.com"},
|
||||
want: []string{"lisa@simpsons.com", "homer@simpsons.com"},
|
||||
},
|
||||
{
|
||||
name: "different domains kept",
|
||||
input: []string{"*@simpsons.com", "lisa@flanders.com", "*@flanders.com"},
|
||||
want: []string{"*@simpsons.com", "*@flanders.com"},
|
||||
},
|
||||
{
|
||||
name: "bare hostname exact dedupe only",
|
||||
input: []string{"simpsons.com", "Simpsons.com", "lisa@simpsons.com"},
|
||||
want: []string{"simpsons.com", "lisa@simpsons.com"},
|
||||
},
|
||||
{
|
||||
name: "blank entries dropped",
|
||||
input: []string{"", " ", "a@b.com"},
|
||||
want: []string{"a@b.com"},
|
||||
},
|
||||
{
|
||||
name: "repair star without at",
|
||||
input: []string{"*vsa.instalily.ai", "lisa@vsa.instalily.ai"},
|
||||
want: []string{"*@vsa.instalily.ai"},
|
||||
},
|
||||
{
|
||||
name: "suffix glob covers specific domains",
|
||||
input: []string{"*@*.shop", "*@alth.shop", "spam@woowstars.shop", "*@other.com"},
|
||||
want: []string{"*@*.shop", "*@other.com"},
|
||||
},
|
||||
{
|
||||
name: "repair star-domain without dot",
|
||||
input: []string{"*@*rumble.com", "user@foo.rumble.com"},
|
||||
want: []string{"*@*.rumble.com"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := Compact(tt.input)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Fatalf("Compact() = %#v, want %#v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterRecipientEntriesForDomain(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := FilterRecipientEntriesForDomain("skaab.nu", []string{
|
||||
"brittis@gronberg.info",
|
||||
"brgr@tspse.net",
|
||||
"abuse@skaab.nu",
|
||||
"postmaster",
|
||||
"ABUSE@SKAAB.NU",
|
||||
})
|
||||
want := []string{"abuse@skaab.nu", "postmaster"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %#v want %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCovers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
broader string
|
||||
specific string
|
||||
want bool
|
||||
}{
|
||||
{"*@simpsons.com", "lisa@simpsons.com", true},
|
||||
{"*@simpsons.com", "*@simpsons.com", true},
|
||||
{"lisa@simpsons.com", "*@simpsons.com", false},
|
||||
{"lisa@simpsons.com", "homer@simpsons.com", false},
|
||||
{"*@simpsons.com", "lisa@flanders.com", false},
|
||||
{"simpsons.com", "lisa@simpsons.com", false},
|
||||
{"", "a@b.com", false},
|
||||
{"*@*.shop", "*@alth.shop", true},
|
||||
{"*@*.shop", "user@alth.shop", true},
|
||||
{"*@*.shop", "*@other.com", false},
|
||||
{"*@simpsons.com", "lisa@mail.simpsons.com", false},
|
||||
{"*vsa.instalily.ai", "x@vsa.instalily.ai", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := Covers(tt.broader, tt.specific)
|
||||
if got != tt.want {
|
||||
t.Fatalf("Covers(%q, %q) = %v, want %v", tt.broader, tt.specific, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user