All checks were successful
check / check (push) Successful in 2m21s
- Remove POST /api/v1/register endpoint entirely - Session creation (POST /api/v1/session) now sets neoirc_auth HttpOnly cookie instead of returning token in JSON body - Login (POST /api/v1/login) now sets neoirc_auth HttpOnly cookie instead of returning token in JSON body - Add PASS IRC command for setting session password (enables multi-client login via POST /api/v1/login) - All per-request auth reads from neoirc_auth cookie instead of Authorization: Bearer header - Cookie properties: HttpOnly, SameSite=Strict, Secure when behind TLS - Logout and QUIT clear the auth cookie - Update CORS to AllowCredentials:true with origin reflection - Remove Authorization from CORS AllowedHeaders - Update CLI client to use cookie jar (net/http/cookiejar) - Remove Token field from SessionResponse - Add SetPassword to DB layer, remove RegisterUser - Comprehensive test updates for cookie-based auth - Add tests: TestPassCommand, TestPassCommandShortPassword, TestPassCommandEmpty, TestSessionCookie - Update README extensively: auth model, API reference, curl examples, security model, design principles, roadmap closes #83
157 lines
2.7 KiB
Go
157 lines
2.7 KiB
Go
package db_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
func TestSetPassword(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
database := setupTestDB(t)
|
|
ctx := t.Context()
|
|
|
|
sessionID, _, _, err :=
|
|
database.CreateSession(ctx, "passuser")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = database.SetPassword(
|
|
ctx, sessionID, "password123",
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify we can now log in with the password.
|
|
loginSID, loginCID, loginToken, err :=
|
|
database.LoginUser(ctx, "passuser", "password123")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if loginSID == 0 || loginCID == 0 || loginToken == "" {
|
|
t.Fatal("expected valid ids and token")
|
|
}
|
|
}
|
|
|
|
func TestSetPasswordThenWrongLogin(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
database := setupTestDB(t)
|
|
ctx := t.Context()
|
|
|
|
sessionID, _, _, err :=
|
|
database.CreateSession(ctx, "wrongpw")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = database.SetPassword(
|
|
ctx, sessionID, "correctpass",
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
loginSID, loginCID, loginToken, loginErr :=
|
|
database.LoginUser(ctx, "wrongpw", "wrongpass12")
|
|
if loginErr == nil {
|
|
t.Fatal("expected error for wrong password")
|
|
}
|
|
|
|
_ = loginSID
|
|
_ = loginCID
|
|
_ = loginToken
|
|
}
|
|
|
|
func TestLoginUser(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
database := setupTestDB(t)
|
|
ctx := t.Context()
|
|
|
|
sessionID, _, _, err :=
|
|
database.CreateSession(ctx, "loginuser")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = database.SetPassword(
|
|
ctx, sessionID, "mypassword",
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
loginSID, loginCID, token, err :=
|
|
database.LoginUser(ctx, "loginuser", "mypassword")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if loginSID == 0 || loginCID == 0 || token == "" {
|
|
t.Fatal("expected valid ids and token")
|
|
}
|
|
|
|
// Verify the new token works.
|
|
_, _, nick, err :=
|
|
database.GetSessionByToken(ctx, token)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if nick != "loginuser" {
|
|
t.Fatalf("expected loginuser, got %s", nick)
|
|
}
|
|
}
|
|
|
|
func TestLoginUserNoPassword(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
database := setupTestDB(t)
|
|
ctx := t.Context()
|
|
|
|
// Create anonymous session (no password).
|
|
anonSID, anonCID, anonToken, err :=
|
|
database.CreateSession(ctx, "anon")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_ = anonSID
|
|
_ = anonCID
|
|
_ = anonToken
|
|
|
|
loginSID, loginCID, loginToken, loginErr :=
|
|
database.LoginUser(ctx, "anon", "anything1")
|
|
if loginErr == nil {
|
|
t.Fatal(
|
|
"expected error for login on passwordless account",
|
|
)
|
|
}
|
|
|
|
_ = loginSID
|
|
_ = loginCID
|
|
_ = loginToken
|
|
}
|
|
|
|
func TestLoginUserNonexistent(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
database := setupTestDB(t)
|
|
ctx := t.Context()
|
|
|
|
loginSID, loginCID, loginToken, err :=
|
|
database.LoginUser(ctx, "ghost", "password123")
|
|
if err == nil {
|
|
t.Fatal("expected error for nonexistent user")
|
|
}
|
|
|
|
_ = loginSID
|
|
_ = loginCID
|
|
_ = loginToken
|
|
}
|