package api
import (
"context"
"errors"
"path/filepath"
"testing"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
// A repository is made in a team's namespace only by somebody who manages
// the team (RFC 0025), the rule team.repo.add already keeps: holding a
// team's name is not a way to put work under it.
func TestOnlyATeamsOwnerCreatesInIt(t *testing.T) {
db, err := oltp.Open(filepath.Join(t.TempDir(), "o.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { db.Close() })
for _, who := range []string{"ada", "bob"} {
if err := db.AddAccount(who, "a-long-enough-password", false); err != nil {
t.Fatal(err)
}
}
if err := db.AddTeam("crew", "Crew", "", "ada"); err != nil {
t.Fatal(err)
}
// The double registers nothing, so the row the team will hold is
// made here, as the registrar would have made it.
if err := db.AddRepo("widgets", t.TempDir(), "", oltp.Public); err != nil {
t.Fatal(err)
}
reg := &fakeRegistry{}
r := ops.NewRegistry()
if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(nil), Registry: reg,
Accounts: newFakeAccounts(), Teams: db}); err != nil {
t.Fatal(err)
}
as := func(who string) context.Context { return ops.WithUser(context.Background(), who) }
if _, err := r.Invoke(as("bob"), "repo.add", repoAddIn{Name: "widgets", Namespace: "crew", Create: true}); !errors.Is(err, ops.ErrForbidden) {
t.Errorf("FAIL: bob created in ada's team: %v", err)
}
if len(reg.added) != 0 {
t.Fatal("FAIL: a refused create reached the registry")
}
got, err := r.Invoke(as("bob"), "repo.name", repoNameIn{Name: "widgets", Namespace: "crew"})
if err != nil || got.(repoNameOut).Free {
t.Errorf("FAIL: the name check offered bob ada's team: %+v %v", got, err)
}
out, err := r.Invoke(as("ada"), "repo.add", repoAddIn{Name: "widgets", Namespace: "crew", Create: true})
if err != nil {
t.Fatalf("FAIL: ada could not create in her own team: %v", err)
}
if o := out.(repoAddOut); o.Namespace != "crew" || o.Handle != "widgets" || db.TeamOfRepo(o.Name) != "crew" {
t.Errorf("FAIL: ada's repository is %+v, held by team %q", o, db.TeamOfRepo(o.Name))
}
}