Files
sub2api/backend/internal/handler/passkey_handler_test.go
T

102 lines
3.4 KiB
Go

package handler
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
)
type passkeySwitchSettingRepo struct {
value string
err error
}
func (r *passkeySwitchSettingRepo) Get(context.Context, string) (*service.Setting, error) {
return nil, service.ErrSettingNotFound
}
func (r *passkeySwitchSettingRepo) GetValue(context.Context, string) (string, error) {
return r.value, r.err
}
func (r *passkeySwitchSettingRepo) Set(context.Context, string, string) error { return nil }
func (r *passkeySwitchSettingRepo) GetMultiple(context.Context, []string) (map[string]string, error) {
return map[string]string{}, nil
}
func (r *passkeySwitchSettingRepo) SetMultiple(context.Context, map[string]string) error {
return nil
}
func (r *passkeySwitchSettingRepo) GetAll(context.Context) (map[string]string, error) {
return map[string]string{}, nil
}
func (r *passkeySwitchSettingRepo) Delete(context.Context, string) error { return nil }
func TestBindPasskeyFinishRequestRejectsOversizedBody(t *testing.T) {
gin.SetMode(gin.TestMode)
recorder := httptest.NewRecorder()
context, _ := gin.CreateTestContext(recorder)
context.Request = httptest.NewRequest(
http.MethodPost,
"/api/v1/auth/passkey/login/finish",
strings.NewReader(`{"credential":"`+strings.Repeat("x", passkeyFinishBodyMaxBytes)+`"}`),
)
context.Request.Header.Set("Content-Type", "application/json")
_, ok := bindPasskeyFinishRequest(context)
require.False(t, ok)
require.Equal(t, http.StatusBadRequest, recorder.Code)
}
func TestPasskeyBeginLoginRejectsDisabledAdminSwitch(t *testing.T) {
gin.SetMode(gin.TestMode)
repo := &passkeySwitchSettingRepo{value: "false"}
settings := service.NewSettingService(repo, &config.Config{
WebAuthn: config.WebAuthnConfig{Enabled: true},
})
handler := NewPasskeyHandler(nil, nil, settings)
recorder := httptest.NewRecorder()
ginContext, _ := gin.CreateTestContext(recorder)
ginContext.Request = httptest.NewRequest(http.MethodPost, "/api/v1/auth/passkey/login/begin", nil)
handler.BeginLogin(ginContext)
require.Equal(t, http.StatusForbidden, recorder.Code)
require.Contains(t, recorder.Body.String(), "PASSKEY_DISABLED")
}
func TestPasskeyBeginLoginReportsSettingStoreFailure(t *testing.T) {
gin.SetMode(gin.TestMode)
settings := service.NewSettingService(
&passkeySwitchSettingRepo{err: errors.New("database unavailable")},
&config.Config{WebAuthn: config.WebAuthnConfig{Enabled: true}},
)
handler := NewPasskeyHandler(nil, nil, settings)
recorder := httptest.NewRecorder()
ginContext, _ := gin.CreateTestContext(recorder)
ginContext.Request = httptest.NewRequest(http.MethodPost, "/api/v1/auth/passkey/login/begin", nil)
handler.BeginLogin(ginContext)
require.Equal(t, http.StatusInternalServerError, recorder.Code)
require.NotContains(t, recorder.Body.String(), "PASSKEY_DISABLED")
}
func TestPasskeyCredentialListRemainsAvailableWhenSignInDisabled(t *testing.T) {
gin.SetMode(gin.TestMode)
handler := NewPasskeyHandler(nil, nil, nil)
recorder := httptest.NewRecorder()
ginContext, _ := gin.CreateTestContext(recorder)
ginContext.Request = httptest.NewRequest(http.MethodGet, "/api/v1/user/passkeys", nil)
handler.List(ginContext)
require.Equal(t, http.StatusUnauthorized, recorder.Code)
require.NotContains(t, recorder.Body.String(), "PASSKEY_DISABLED")
}