Skip to content
quarry Artifact [d055fdfa55]
Login

Artifact [d055fdfa55]

Artifact d055fdfa556b7559966d61e858c30e4e30bf294de0b448849570e91ebfd34029:


package oltp

import (
	"errors"
	"testing"
)

func TestWithdrawnInviteFreesTheName(t *testing.T) {
	db := testDB(t)
	if err := db.AddRepo("shared", t.TempDir(), "", "public"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.InviteAccount("northrup", "[email protected]", false); err != nil {
		t.Fatal(err)
	}
	if err := db.Grant("northrup", "shared", Write); err != nil {
		t.Fatal(err)
	}
	if err := db.WithdrawInvite("northrup"); err != nil {
		t.Fatal(err)
	}
	if _, ok := db.AccountByName("northrup"); ok {
		t.Fatal("withdrawn invite left the account")
	}
	if db.Tombstoned("northrup") {
		t.Fatal("withdrawn invite retired the name")
	}
	for _, q := range []string{
		`SELECT count(*) FROM invite WHERE account = 'northrup'`,
		`SELECT count(*) FROM repo_caps WHERE account = 'northrup'`,
	} {
		if n := countRows(t, db, q); n != 0 {
			t.Fatalf("%s: %d rows left", q, n)
		}
	}
	// The name is free: someone else can be invited under it, and they
	// inherit none of the withdrawn account's grants.
	if _, err := db.InviteAccount("northrup", "[email protected]", false); err != nil {
		t.Fatalf("re-invite after withdraw: %v", err)
	}
	if caps, _ := db.CapsOf("northrup", "shared"); caps != "" {
		t.Fatalf("successor inherited caps %q", caps)
	}
}

func TestWithdrawRefusedForAUsedAccount(t *testing.T) {
	db := testDB(t)
	if err := db.AddAccount("bob", "pw-bob-12345", false); err != nil {
		t.Fatal(err)
	}
	tok, err := db.InviteAccount("jan", "[email protected]", false)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := db.RedeemInvite(tok, "pw-jan-12345"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.InviteAccount("lou", "[email protected]", false); err != nil {
		t.Fatal(err)
	}
	if _, err := db.w.Exec(`UPDATE account SET last_login = 'x' WHERE name = 'lou'`); err != nil {
		t.Fatal(err)
	}
	for _, name := range []string{"bob", "jan", "lou"} {
		var ref Refusal
		if err := db.WithdrawInvite(name); !errors.As(err, &ref) {
			t.Fatalf("withdraw %s: want Refusal, got %v", name, err)
		}
		if _, ok := db.AccountByName(name); !ok {
			t.Fatalf("refused withdraw removed %s", name)
		}
	}
	if err := db.WithdrawInvite("nobody"); !errors.Is(err, ErrNoAccount) {
		t.Fatalf("withdraw unknown: want ErrNoAccount, got %v", err)
	}
}

func TestLastSeenFollowsUseNotJustSignIn(t *testing.T) {
	db := testDB(t)
	if err := db.AddAccount("bob", "pw-bob-12345", false); err != nil {
		t.Fatal(err)
	}
	tok, _, ok := db.NewSession("bob", "pw-bob-12345")
	if !ok {
		t.Fatal("sign-in failed")
	}
	if _, err := db.w.Exec(`UPDATE session SET last_seen = '2000-01-01T00:00:00Z'`); err != nil {
		t.Fatal(err)
	}
	if _, err := db.w.Exec(`UPDATE account SET last_seen = '2000-01-01T00:00:00Z', last_login = '2000-01-01T00:00:00Z'`); err != nil {
		t.Fatal(err)
	}
	if _, ok := db.SessionAccount(tok); !ok {
		t.Fatal("session did not resolve")
	}
	a, _ := db.AccountByName("bob")
	if a.LastSeen == "2000-01-01T00:00:00Z" || a.LastSeen == "" {
		t.Fatalf("a page view did not move last_seen: %q", a.LastSeen)
	}
	if a.LastLogin != "2000-01-01T00:00:00Z" {
		t.Fatalf("a page view moved last_login: %q", a.LastLogin)
	}
	// Seen accounts are used accounts: their invite cannot be withdrawn.
	if err := db.WithdrawInvite("bob"); err == nil {
		t.Fatal("withdrew a used account")
	}
}