package api
import (
"context"
"testing"
"craftdesign.group/quarry/internal/ops"
)
// A grant tells its SUBJECT, transactionally, never the person who
// made the change. RFC 0005's account.caps only exists to be raised at
// exactly this moment (register.go's account.grant/.revoke).
func TestAccessChangedMailsTheSubjectNotTheActor(t *testing.T) {
accts := newFakeAccounts()
accts.accounts["dan"] = Account{Name: "dan", Admin: true}
accts.accounts["eve"] = Account{Name: "eve", Email: "[email protected]"}
mail := &fakeMail{}
r := ops.NewRegistry()
if err := RegisterAll(r, Deps{Version: "v", Accounts: accts, Mail: mail,
Repos: NewRepos(map[string]*Repo{"quarry": {}})}); err != nil {
t.Fatal(err)
}
ctx := ops.WithUser(context.Background(), "dan")
if _, err := r.Invoke(ctx, "account.grant", accountGrantIn{Name: "eve", Repo: "quarry", Role: "developer"}); err != nil {
t.Fatal(err)
}
if !mail.to("[email protected]") {
t.Fatalf("the subject was not mailed: %+v", mail.sent)
}
if len(mail.sent) != 1 {
t.Fatalf("expected exactly one message, got %+v", mail.sent)
}
// A revoke tells the same way, and a re-grant of the SAME role
// (nothing actually changed) tells nobody.
if _, err := r.Invoke(ctx, "account.grant", accountGrantIn{Name: "eve", Repo: "quarry", Role: "developer"}); err != nil {
t.Fatal(err)
}
if len(mail.sent) != 1 {
t.Fatalf("a no-op re-grant sent mail: %+v", mail.sent)
}
if _, err := r.Invoke(ctx, "account.revoke", accountRevokeIn{Name: "eve", Repo: "quarry"}); err != nil {
t.Fatal(err)
}
if len(mail.sent) != 2 || mail.sent[1].To != "[email protected]" {
t.Fatalf("revoke did not mail the subject: %+v", mail.sent)
}
}
// Granting yourself something (repo.add's owner grant) must not mail
// you about your own action.
func TestAccessChangedSilentWhenActorIsSubject(t *testing.T) {
accts := newFakeAccounts()
accts.accounts["dan"] = Account{Name: "dan", Email: "[email protected]"}
mail := &fakeMail{}
d := Deps{Accounts: accts, Mail: mail}
d.AccessChanged(context.Background(), "dan", "dan", "quarry", "", "admin")
if len(mail.sent) != 0 {
t.Fatalf("an account was mailed about its own action: %+v", mail.sent)
}
}
// With no mail plane, AccessChanged still runs its other effects (it
// must not panic or error) and simply sends nothing.
func TestAccessChangedWithNoMailPlaneSendsNothing(t *testing.T) {
accts := newFakeAccounts()
accts.accounts["eve"] = Account{Name: "eve", Email: "[email protected]"}
d := Deps{Accounts: accts} // no Mail
d.AccessChanged(context.Background(), "dan", "eve", "quarry", "", "developer")
// Nothing to assert beyond "did not panic" — there is no mail log
// to check, which is exactly the point: a forge with no mail
// provider configured for this Deps sends nothing, silently.
}