feat(auth): implement user and device authentication

This commit is contained in:
QiuSW
2026-07-26 15:18:48 +08:00
parent c5d3b215ff
commit 49db5b8305
66 changed files with 6216 additions and 271 deletions
@@ -9,6 +9,9 @@ import (
"regexp"
"strings"
"testing"
"time"
"cmroubao/backend-api/internal/domain"
"github.com/gin-gonic/gin"
)
@@ -114,9 +117,11 @@ func TestSafeRecoveryReturnsStableErrorWithoutLoggingRequestHeaders(t *testing.T
func TestRouterRequiresDependencies(t *testing.T) {
valid := RouterDependencies{
Database: fakePinger{},
RegisterAdminRoutes: discardRoutes,
LogEvent: discardEvent,
Database: fakePinger{},
RegisterPublicRoutes: discardRoutes,
RegisterAdminRoutes: discardRoutes,
AdminSessions: allowAdminAuthenticator{},
LogEvent: discardEvent,
}
missingDatabase := valid
missingDatabase.Database = nil
@@ -128,6 +133,16 @@ func TestRouterRequiresDependencies(t *testing.T) {
if _, err := NewRouter(missingRoutes); err == nil {
t.Fatal("NewRouter(nil routes) error = nil")
}
missingPublicRoutes := valid
missingPublicRoutes.RegisterPublicRoutes = nil
if _, err := NewRouter(missingPublicRoutes); err == nil {
t.Fatal("NewRouter(nil public routes) error = nil")
}
missingAuth := valid
missingAuth.AdminSessions = nil
if _, err := NewRouter(missingAuth); err == nil {
t.Fatal("NewRouter(nil admin auth) error = nil")
}
missingLogger := valid
missingLogger.LogEvent = nil
if _, err := NewRouter(missingLogger); err == nil {
@@ -140,9 +155,11 @@ func newTestRouter(
logEvent EventLogger,
) (http.Handler, error) {
return NewRouter(RouterDependencies{
Database: database,
RegisterAdminRoutes: discardRoutes,
LogEvent: logEvent,
Database: database,
RegisterPublicRoutes: discardRoutes,
RegisterAdminRoutes: discardRoutes,
AdminSessions: allowAdminAuthenticator{},
LogEvent: logEvent,
})
}
@@ -223,6 +240,21 @@ func discardEvent(string) {}
func discardRoutes(gin.IRoutes) error { return nil }
type allowAdminAuthenticator struct{}
func (allowAdminAuthenticator) AuthenticateAdmin(
context.Context,
string,
) (domain.AuthPrincipal, error) {
return domain.AuthPrincipal{
UserID: "00000000-0000-4000-8000-000000000099",
Username: "admin",
Role: domain.UserRoleAdmin,
SessionID: "admin-session",
ExpiresAt: time.Now().Add(time.Hour),
}, nil
}
var requestIDPattern = regexp.MustCompile(
`^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`,
)