diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-19 19:32:30 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-19 19:32:30 +0300 |
| commit | 965b36f3e09a0d4cdbb69cb3f423ab01fecf2419 (patch) | |
| tree | c7271588848864b88c67e82818153d08c91dae64 | |
| parent | 3779053951f338076fcc448daf9bee9ada18cf54 (diff) | |
Inject narrow api.Authenticator into NewMiddleware
The middleware previously took the full service.AuthService, but only
called three methods on it. Define a narrow api.Authenticator interface
(AuthenticateBearer, CountUsers, GetUserByID) and inject that instead,
fixing the ISP violation. service.AuthService satisfies the new
interface structurally, so callers and tests need no changes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| -rw-r--r-- | player-server/internal/api/middleware.go | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/player-server/internal/api/middleware.go b/player-server/internal/api/middleware.go index ec7c1a7..5566e42 100644 --- a/player-server/internal/api/middleware.go +++ b/player-server/internal/api/middleware.go @@ -8,7 +8,6 @@ import ( "codeberg.org/snonux/player/internal/auth" "codeberg.org/snonux/player/internal/model" - "codeberg.org/snonux/player/internal/service" ) type ctxKey int @@ -20,6 +19,24 @@ const ( userCtxKey ) +// Authenticator is the narrow auth interface needed by middleware. +// +// It exposes only the methods middleware actually calls, satisfying the +// Interface Segregation Principle: callers (and test doubles) need not +// implement the full service.AuthService surface (bootstrap, login, API +// token CRUD, etc.) just to wire up request authentication. +// +// service.AuthService satisfies this interface structurally, so the live +// server simply passes its concrete service in. +type Authenticator interface { + // AuthenticateBearer validates a Bearer token and returns a synthetic session. + AuthenticateBearer(ctx context.Context, plaintext string) (*model.Session, error) + // CountUsers reports the number of registered users (used by BootstrapRedirect). + CountUsers(ctx context.Context) (int, error) + // GetUserByID returns a user by database ID (used by RequireAdmin). + GetUserByID(ctx context.Context, id int64) (*model.User, error) +} + // Middleware holds dependencies for middleware constructors. // // publicPaths and publicPrefixes form a route registry used by @@ -29,16 +46,22 @@ const ( // the bypass set — no hidden hardcoded whitelist that silently 401s/redirects // new routes the developer forgot to add. type Middleware struct { - authSvc service.AuthService + authSvc Authenticator sm auth.SessionManager publicPaths map[string]bool publicPrefixes []string } // NewMiddleware creates middleware handlers. +// +// The auth dependency is the narrow Authenticator interface rather than the +// full service.AuthService — middleware only needs three methods, and the +// smaller surface keeps tests cheap and prevents accidental coupling to +// unrelated auth-service operations. +// // The public route registry starts empty; callers register public paths // via RegisterPublic / RegisterPublicPrefix as routes are wired up. -func NewMiddleware(authSvc service.AuthService, sm auth.SessionManager) *Middleware { +func NewMiddleware(authSvc Authenticator, sm auth.SessionManager) *Middleware { return &Middleware{ authSvc: authSvc, sm: sm, |
