Skip to content
quarry Artifact [7e2b9a5398]
Login

Artifact [7e2b9a5398]

Artifact 7e2b9a5398f50dde7d2d37b0b67ba1f6bee7c86f350943dea3d2df9c36a5743d:


package oltp

import (
	"path/filepath"
	"testing"
)

// An invite is an account that exists but cannot sign in until its
// owner sets a password through the one-time link. Redeeming spends the
// link; a second redemption fails.
func TestInviteClaimsAnAccountOnce(t *testing.T) {
	db, err := Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	token, err := db.InviteAccount("eve", "[email protected]", false)
	if err != nil || token == "" {
		t.Fatalf("invite: %q %v", token, err)
	}
	accts, _ := db.Accounts()
	if len(accts) != 1 || !accts[0].Pending || accts[0].Email != "[email protected]" {
		t.Fatalf("invited account listed as %+v", accts)
	}
	if _, ok := db.Authenticate("eve", ""); ok {
		t.Fatalf("an unclaimed invite signs in with an empty password")
	}
	if name, ok := db.InviteFor(token); !ok || name != "eve" {
		t.Fatalf("InviteFor = %q %v", name, ok)
	}
	if _, ok := db.InviteFor("not-a-token"); ok {
		t.Fatalf("an unknown token is live")
	}
	if name, err := db.RedeemInvite(token, "hunter22"); err != nil || name != "eve" {
		t.Fatalf("redeem: %q %v", name, err)
	}
	if _, ok := db.Authenticate("eve", "hunter22"); !ok {
		t.Fatalf("the claimed account cannot sign in")
	}
	if _, err := db.RedeemInvite(token, "again"); err == nil {
		t.Fatalf("a spent invite was redeemed twice")
	}
	if _, err := db.InviteAccount("eve", "x@y", false); err == nil {
		t.Fatalf("an account with a password was re-invited")
	}
	if a, _ := db.AccountByName("eve"); a.Pending {
		t.Errorf("claimed account still pending: %+v", a)
	}
}

// Disabling shuts the door at once: sign-in fails and every live
// session is gone, on every device. Re-enabling reopens sign-in.
func TestDisableEndsSessionsAndBlocksSignIn(t *testing.T) {
	db, err := Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	if err := db.AddAccount("dan", "pw", false); err != nil {
		t.Fatal(err)
	}
	tok1, _, ok1 := db.NewSessionFrom("dan", "pw", "10.0.0.1", "phone")
	tok2, _, ok2 := db.NewSessionFrom("dan", "pw", "10.0.0.2", "laptop")
	if !ok1 || !ok2 {
		t.Fatal("two devices could not sign in")
	}
	ss, _ := db.Sessions("dan")
	if len(ss) != 2 || ss[0].IP == "" || ss[0].Agent == "" || ss[0].ID == "" {
		t.Fatalf("sessions = %+v", ss)
	}
	if a, _ := db.AccountByName("dan"); a.LastLogin == "" {
		t.Errorf("last login not recorded")
	}
	// Ending one device leaves the other signed in.
	if err := db.EndSessionID(SessionID(tok1), "dan"); err != nil {
		t.Fatal(err)
	}
	if _, ok := db.SessionAccount(tok1); ok {
		t.Errorf("ended session still resolves")
	}
	if _, ok := db.SessionAccount(tok2); !ok {
		t.Errorf("the other device was signed out too")
	}
	// The owner guard: another account cannot end dan's session.
	if err := db.EndSessionID(SessionID(tok2), "mallory"); err != nil {
		t.Fatal(err)
	}
	if _, ok := db.SessionAccount(tok2); !ok {
		t.Errorf("a different account ended dan's session")
	}
	if err := db.SetDisabled("dan", true); err != nil {
		t.Fatal(err)
	}
	if _, ok := db.SessionAccount(tok2); ok {
		t.Errorf("a disabled account's session still resolves")
	}
	if _, _, ok := db.NewSession("dan", "pw"); ok {
		t.Errorf("a disabled account signed in")
	}
	if a, _ := db.AccountByName("dan"); a.Disabled == "" {
		t.Errorf("account not marked disabled")
	}
	if err := db.SetDisabled("dan", false); err != nil {
		t.Fatal(err)
	}
	if _, _, ok := db.NewSession("dan", "pw"); !ok {
		t.Errorf("a re-enabled account cannot sign in")
	}
	if err := db.SetDisabled("nobody", true); err == nil {
		t.Errorf("disabling an unknown account succeeded")
	}
}