cdffb15004
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
package store
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func sampleAccount() Account {
|
|
return Account{
|
|
Name: "work", Mode: "RO",
|
|
IMAPHost: "imap.example.com", IMAPPort: 993, IMAPSecurity: "tls",
|
|
AuthType: "password", Username: "me@example.com",
|
|
Password: "s3cr3t", SubjectRegex: "",
|
|
}
|
|
}
|
|
|
|
func TestAddGetAccountDecryptsSecret(t *testing.T) {
|
|
s := openTemp(t)
|
|
id, err := s.AddAccount(sampleAccount())
|
|
if err != nil {
|
|
t.Fatalf("AddAccount: %v", err)
|
|
}
|
|
if id == 0 {
|
|
t.Fatal("want non-zero id")
|
|
}
|
|
got, err := s.GetAccount("work")
|
|
if err != nil {
|
|
t.Fatalf("GetAccount: %v", err)
|
|
}
|
|
if got.Password != "s3cr3t" {
|
|
t.Fatalf("password not decrypted: %q", got.Password)
|
|
}
|
|
if got.Mode != "RO" || got.IMAPPort != 993 {
|
|
t.Fatalf("fields wrong: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestAddGetAccountRoundTripsSMTP(t *testing.T) {
|
|
s := openTemp(t)
|
|
a := sampleAccount()
|
|
a.Mode = "RW"
|
|
a.SMTPHost = "smtp.example.com"
|
|
a.SMTPPort = 465
|
|
a.SMTPSecurity = "tls"
|
|
if _, err := s.AddAccount(a); err != nil {
|
|
t.Fatalf("AddAccount: %v", err)
|
|
}
|
|
got, err := s.GetAccount("work")
|
|
if err != nil {
|
|
t.Fatalf("GetAccount: %v", err)
|
|
}
|
|
if got.SMTPHost != "smtp.example.com" || got.SMTPPort != 465 || got.SMTPSecurity != "tls" {
|
|
t.Fatalf("SMTP fields not round-tripped: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestPasswordStoredEncrypted(t *testing.T) {
|
|
s := openTemp(t)
|
|
_, _ = s.AddAccount(sampleAccount())
|
|
var blob []byte
|
|
if err := s.db.QueryRow("SELECT enc_password FROM accounts WHERE name='work'").Scan(&blob); err != nil {
|
|
t.Fatalf("query: %v", err)
|
|
}
|
|
if string(blob) == "s3cr3t" || len(blob) == 0 {
|
|
t.Fatalf("password not encrypted at rest: %q", blob)
|
|
}
|
|
}
|
|
|
|
func TestGetAccountNotFound(t *testing.T) {
|
|
s := openTemp(t)
|
|
if _, err := s.GetAccount("nope"); !errors.Is(err, ErrAccountNotFound) {
|
|
t.Fatalf("want ErrAccountNotFound, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestListAccountsOmitsSecrets(t *testing.T) {
|
|
s := openTemp(t)
|
|
_, _ = s.AddAccount(sampleAccount())
|
|
list, err := s.ListAccounts()
|
|
if err != nil || len(list) != 1 {
|
|
t.Fatalf("list: %v len=%d", err, len(list))
|
|
}
|
|
if list[0].Password != "" {
|
|
t.Fatal("ListAccounts must not return secrets")
|
|
}
|
|
}
|
|
|
|
func TestSendFromFallsBackToUsername(t *testing.T) {
|
|
a := Account{Username: "login@example.com"}
|
|
if got := a.SendFrom(); got != "login@example.com" {
|
|
t.Fatalf("blank from-address should fall back to username, got %q", got)
|
|
}
|
|
a.FromAddress = "Steve Cliff <me@stevecliff.com>"
|
|
if got := a.SendFrom(); got != "Steve Cliff <me@stevecliff.com>" {
|
|
t.Fatalf("set from-address should win, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAddGetAccountRoundTripsFromAddress(t *testing.T) {
|
|
s := openTemp(t)
|
|
a := sampleAccount()
|
|
a.FromAddress = "Steve Cliff <me@stevecliff.com>"
|
|
if _, err := s.AddAccount(a); err != nil {
|
|
t.Fatalf("AddAccount: %v", err)
|
|
}
|
|
got, err := s.GetAccount("work")
|
|
if err != nil {
|
|
t.Fatalf("GetAccount: %v", err)
|
|
}
|
|
if got.FromAddress != "Steve Cliff <me@stevecliff.com>" {
|
|
t.Fatalf("FromAddress not round-tripped: %q", got.FromAddress)
|
|
}
|
|
}
|