mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 22:37:28 +00:00
- setup.sh: idempotent one-shot droplet provisioner — agentbbs on :22 (admin OpenSSH moved to :2202), rootless podman, Caddy front end for https://bbs.profullstack.com with tilde-style /~user homepages - internal/sites + domain@ SSH route: self-service custom domains (ssh domain@host add example.com) backed by a symlink farm and an on-demand-TLS ask endpoint so Caddy only issues certs for mapped hosts - internal/mail + join@ email verification: optional email at signup, confirmation link served by a loopback /verify endpoint behind Caddy - internal/source + cmd/ascii-live: live video → terminal ASCII groundwork (docs/ascii-live.md) - store: additive sqlite migrations (email/verify columns, domains table) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package store
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestEmailVerificationRoundtrip(t *testing.T) {
|
|
st, err := Open(filepath.Join(t.TempDir(), "t.db"))
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer st.Close()
|
|
|
|
u, err := st.EnsureUser("alice", "member", "SHA256:aaa")
|
|
if err != nil {
|
|
t.Fatalf("ensure: %v", err)
|
|
}
|
|
if u.EmailVerified {
|
|
t.Fatal("new user should be unverified")
|
|
}
|
|
|
|
if err := st.SetEmailVerification(u.ID, "alice@example.com", "tok123"); err != nil {
|
|
t.Fatalf("set: %v", err)
|
|
}
|
|
// Email is stored but not yet verified.
|
|
got, _, err := st.UserByFingerprint("SHA256:aaa")
|
|
if err != nil {
|
|
t.Fatalf("byfp: %v", err)
|
|
}
|
|
if got.Email != "alice@example.com" || got.EmailVerified {
|
|
t.Fatalf("pre-verify state wrong: %+v", got)
|
|
}
|
|
|
|
// Wrong token does nothing.
|
|
if _, ok, _ := st.VerifyEmail("nope"); ok {
|
|
t.Fatal("bad token should not verify")
|
|
}
|
|
|
|
// Correct token verifies and returns the account.
|
|
vu, ok, err := st.VerifyEmail("tok123")
|
|
if err != nil || !ok {
|
|
t.Fatalf("verify: ok=%v err=%v", ok, err)
|
|
}
|
|
if vu.Name != "alice" || !vu.EmailVerified {
|
|
t.Fatalf("verify returned wrong user: %+v", vu)
|
|
}
|
|
|
|
// Token is single-use (cleared after verification).
|
|
if _, ok, _ := st.VerifyEmail("tok123"); ok {
|
|
t.Fatal("token should be consumed after first use")
|
|
}
|
|
final, _, _ := st.UserByName("alice")
|
|
if !final.EmailVerified {
|
|
t.Fatal("user should remain verified")
|
|
}
|
|
}
|
|
|
|
func TestVerifyEmailEmptyToken(t *testing.T) {
|
|
st, err := Open(filepath.Join(t.TempDir(), "t.db"))
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer st.Close()
|
|
if _, ok, err := st.VerifyEmail(""); ok || err != nil {
|
|
t.Fatalf("empty token must be a clean miss: ok=%v err=%v", ok, err)
|
|
}
|
|
}
|