305 lines
8.8 KiB
Go
305 lines
8.8 KiB
Go
package handler_test
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git.ekzyis.com/ekzyis/delphi.market/server/auth"
|
|
"git.ekzyis.com/ekzyis/delphi.market/server/router/context"
|
|
"git.ekzyis.com/ekzyis/delphi.market/server/router/handler"
|
|
"git.ekzyis.com/ekzyis/delphi.market/test"
|
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func init() {
|
|
test.Init(&db)
|
|
}
|
|
|
|
func TestLnAuthSignup(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
sc = context.Context{Db: db}
|
|
e *echo.Echo
|
|
c echo.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
cookies []*http.Cookie
|
|
sessionId string
|
|
dbSessionId string
|
|
err error
|
|
)
|
|
|
|
e, req, rec = test.HTTPMocks("GET", "/signup/lightning", nil)
|
|
c = e.NewContext(req, rec)
|
|
c.SetParamNames("method")
|
|
c.SetParamValues("lightning")
|
|
|
|
handler.HandleAuth(sc, "register")(c)
|
|
assert.Equal(http.StatusOK, rec.Code, "wrong status code")
|
|
|
|
// Set-Cookie header present
|
|
cookies = rec.Result().Cookies()
|
|
assert.Equal(1, len(cookies), "wrong number of Set-Cookie headers")
|
|
assert.Equal("session", cookies[0].Name, "wrong cookie name")
|
|
|
|
// new challenge inserted which matches cookie value
|
|
sessionId = cookies[0].Value
|
|
err = db.QueryRow("SELECT session_id FROM lnauth WHERE session_id = $1", sessionId).Scan(&dbSessionId)
|
|
assert.NoError(err)
|
|
assert.Equal(sessionId, dbSessionId, "wrong session id")
|
|
}
|
|
|
|
func TestLnAuthSignupCallbackUserNotExists(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
e *echo.Echo
|
|
c echo.Context
|
|
sc context.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
lnAuth *auth.LnAuth
|
|
sk *secp256k1.PrivateKey
|
|
pk *secp256k1.PublicKey
|
|
sig string
|
|
key string
|
|
sessionId string
|
|
userId int
|
|
count int
|
|
err error
|
|
)
|
|
|
|
lnAuth, err = auth.NewLnAuth("register")
|
|
assert.NoErrorf(err, "error creating challenge")
|
|
|
|
err = db.QueryRow(
|
|
"INSERT INTO lnauth(k1, lnurl) VALUES($1, $2) RETURNING session_id",
|
|
lnAuth.K1, lnAuth.LNURL).Scan(&sessionId)
|
|
assert.NoError(err, "error creating challenge")
|
|
|
|
sk, pk, err = test.GenerateKeyPair()
|
|
assert.NoError(err, "error generating keypair")
|
|
|
|
sig, err = test.Sign(sk, lnAuth.K1)
|
|
assert.NoError(err, "error signing k1")
|
|
|
|
key = hex.EncodeToString(pk.SerializeCompressed())
|
|
|
|
sc = context.Context{Db: db}
|
|
e, req, rec = test.HTTPMocks(
|
|
"GET",
|
|
fmt.Sprintf("/api/lnauth?tag=login&k1=%s&key=%s&sig=%s&action=%s", lnAuth.K1, key, sig, "register"),
|
|
nil)
|
|
c = e.NewContext(req, rec)
|
|
|
|
handler.HandleLnAuthCallback(sc)(c)
|
|
assert.Equal(http.StatusOK, rec.Code, "wrong status code")
|
|
|
|
// user created
|
|
err = db.QueryRow("SELECT id FROM users WHERE ln_pubkey = $1", key).Scan(&userId)
|
|
assert.NoError(err, "error fetching user")
|
|
|
|
// session created
|
|
err = db.QueryRow("SELECT COUNT(1) FROM sessions WHERE id = $1 AND user_id = $2", sessionId, userId).Scan(&count)
|
|
assert.NoError(err, "error fetching session")
|
|
assert.Equal(1, count, "invalid session count")
|
|
|
|
// challenge deleted
|
|
err = db.QueryRow("SELECT COUNT(1) FROM lnauth WHERE k1 = $1", lnAuth.K1).Scan(&count)
|
|
assert.NoError(err, "error fetching challenge")
|
|
assert.Equal(count, 0, "challenge not deleted")
|
|
}
|
|
|
|
func TestLnAuthSignupCallbackUserExists(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
e *echo.Echo
|
|
c echo.Context
|
|
sc context.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
lnAuth *auth.LnAuth
|
|
sk *secp256k1.PrivateKey
|
|
pk *secp256k1.PublicKey
|
|
sig string
|
|
key string
|
|
sessionId string
|
|
err error
|
|
)
|
|
|
|
lnAuth, err = auth.NewLnAuth("register")
|
|
assert.NoErrorf(err, "error creating challenge")
|
|
|
|
err = db.QueryRow(
|
|
"INSERT INTO lnauth(k1, lnurl) VALUES($1, $2) RETURNING session_id",
|
|
lnAuth.K1, lnAuth.LNURL).Scan(&sessionId)
|
|
assert.NoError(err, "error creating challenge")
|
|
|
|
sk, pk, err = test.GenerateKeyPair()
|
|
assert.NoError(err, "error generating keypair")
|
|
|
|
sig, err = test.Sign(sk, lnAuth.K1)
|
|
assert.NoError(err, "error signing k1")
|
|
|
|
key = hex.EncodeToString(pk.SerializeCompressed())
|
|
|
|
// create user before signup
|
|
_, err = db.Exec("INSERT INTO users(ln_pubkey) VALUES($1) RETURNING id", key)
|
|
assert.NoError(err, "error creating user")
|
|
|
|
sc = context.Context{Db: db}
|
|
e, req, rec = test.HTTPMocks(
|
|
"GET",
|
|
fmt.Sprintf("/api/lnauth?tag=login&k1=%s&key=%s&sig=%s&action=%s", lnAuth.K1, key, sig, "register"),
|
|
nil)
|
|
c = e.NewContext(req, rec)
|
|
|
|
// does not throw an error for UX reasons
|
|
handler.HandleLnAuthCallback(sc)(c)
|
|
assert.Equal(http.StatusOK, rec.Code, "wrong status code")
|
|
}
|
|
|
|
func TestLnAuthLogin(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
sc = context.Context{Db: db}
|
|
e *echo.Echo
|
|
c echo.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
cookies []*http.Cookie
|
|
sessionId string
|
|
dbSessionId string
|
|
err error
|
|
)
|
|
|
|
e, req, rec = test.HTTPMocks("GET", "/login/lightning", nil)
|
|
c = e.NewContext(req, rec)
|
|
c.SetParamNames("method")
|
|
c.SetParamValues("lightning")
|
|
|
|
err = handler.HandleAuth(sc, "login")(c)
|
|
assert.NoError(err, "handler returned error")
|
|
|
|
// Set-Cookie header present
|
|
cookies = rec.Result().Cookies()
|
|
assert.Equal(len(cookies), 1, "wrong number of Set-Cookie headers")
|
|
assert.Equal("session", cookies[0].Name, "wrong cookie name")
|
|
|
|
// new challenge inserted which matches cookie value
|
|
sessionId = cookies[0].Value
|
|
err = db.QueryRow("SELECT session_id FROM lnauth WHERE session_id = $1", sessionId).Scan(&dbSessionId)
|
|
assert.NoError(err)
|
|
assert.Equal(sessionId, dbSessionId, "wrong session id")
|
|
}
|
|
|
|
func TestLnAuthLoginCallbackUserNotExists(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
e *echo.Echo
|
|
c echo.Context
|
|
sc context.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
lnAuth *auth.LnAuth
|
|
sk *secp256k1.PrivateKey
|
|
pk *secp256k1.PublicKey
|
|
sig string
|
|
key string
|
|
sessionId string
|
|
err error
|
|
)
|
|
|
|
lnAuth, err = auth.NewLnAuth("login")
|
|
assert.NoErrorf(err, "error creating challenge")
|
|
|
|
err = db.QueryRow(
|
|
"INSERT INTO lnauth(k1, lnurl) VALUES($1, $2) RETURNING session_id",
|
|
lnAuth.K1, lnAuth.LNURL).Scan(&sessionId)
|
|
assert.NoError(err, "error creating challenge")
|
|
|
|
sk, pk, err = test.GenerateKeyPair()
|
|
assert.NoError(err, "error generating keypair")
|
|
|
|
sig, err = test.Sign(sk, lnAuth.K1)
|
|
assert.NoError(err, "error signing k1")
|
|
|
|
key = hex.EncodeToString(pk.SerializeCompressed())
|
|
|
|
sc = context.Context{Db: db}
|
|
e, req, rec = test.HTTPMocks(
|
|
"GET",
|
|
fmt.Sprintf("/api/lnauth?tag=login&k1=%s&key=%s&sig=%s&action=%s", lnAuth.K1, key, sig, "login"),
|
|
nil)
|
|
c = e.NewContext(req, rec)
|
|
|
|
// must throw error because user does not exist
|
|
handler.HandleLnAuthCallback(sc)(c)
|
|
assert.Equal(http.StatusNotFound, rec.Code, "wrong status code")
|
|
assert.Contains(rec.Body.String(), "\"reason\":\"user not found\"", "user check failed")
|
|
}
|
|
|
|
func TestLnAuthLoginCallbackUserExists(t *testing.T) {
|
|
var (
|
|
assert = assert.New(t)
|
|
e *echo.Echo
|
|
c echo.Context
|
|
sc context.Context
|
|
req *http.Request
|
|
rec *httptest.ResponseRecorder
|
|
lnAuth *auth.LnAuth
|
|
sk *secp256k1.PrivateKey
|
|
pk *secp256k1.PublicKey
|
|
sig string
|
|
key string
|
|
sessionId string
|
|
userId int
|
|
count int
|
|
err error
|
|
)
|
|
|
|
lnAuth, err = auth.NewLnAuth("login")
|
|
assert.NoErrorf(err, "error creating challenge")
|
|
|
|
err = db.QueryRow(
|
|
"INSERT INTO lnauth(k1, lnurl) VALUES($1, $2) RETURNING session_id",
|
|
lnAuth.K1, lnAuth.LNURL).Scan(&sessionId)
|
|
assert.NoError(err, "error creating challenge")
|
|
|
|
sk, pk, err = test.GenerateKeyPair()
|
|
assert.NoError(err, "error generating keypair")
|
|
|
|
sig, err = test.Sign(sk, lnAuth.K1)
|
|
assert.NoError(err, "error signing k1")
|
|
|
|
key = hex.EncodeToString(pk.SerializeCompressed())
|
|
|
|
// create user such that login does not fail
|
|
err = db.QueryRow("INSERT INTO users(ln_pubkey) VALUES($1) RETURNING id", key).Scan(&userId)
|
|
assert.NoError(err, "error creating user")
|
|
|
|
sc = context.Context{Db: db}
|
|
e, req, rec = test.HTTPMocks(
|
|
"GET",
|
|
fmt.Sprintf("/api/lnauth?tag=login&k1=%s&key=%s&sig=%s&action=%s", lnAuth.K1, key, sig, "login"),
|
|
nil)
|
|
c = e.NewContext(req, rec)
|
|
|
|
handler.HandleLnAuthCallback(sc)(c)
|
|
assert.Equal(http.StatusOK, rec.Code, "wrong status code")
|
|
|
|
// session created
|
|
err = db.QueryRow("SELECT COUNT(1) FROM sessions WHERE id = $1 AND user_id = $2", sessionId, userId).Scan(&count)
|
|
assert.NoError(err, "error fetching session")
|
|
assert.Equal(1, count, "invalid session count")
|
|
|
|
// challenge deleted
|
|
err = db.QueryRow("SELECT COUNT(1) FROM lnauth WHERE k1 = $1", lnAuth.K1).Scan(&count)
|
|
assert.NoError(err, "error fetching challenge")
|
|
assert.Equal(count, 0, "challenge not deleted")
|
|
}
|