Skip to content

Commit f404c2e

Browse files
authored
feat: use dig for di in services and controllers (#936)
1 parent a0e74cd commit f404c2e

39 files changed

Lines changed: 791 additions & 360 deletions

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
github.com/stretchr/testify v1.11.1
2222
github.com/tinyauthapp/paerser v0.0.0-20260410140347-85c3740d6298
2323
github.com/weppos/publicsuffix-go v0.50.3
24+
go.uber.org/dig v1.19.0
2425
golang.org/x/crypto v0.52.0
2526
golang.org/x/oauth2 v0.36.0
2627
golang.org/x/tools v0.45.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09
485485
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
486486
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
487487
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
488+
go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
489+
go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
488490
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
489491
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
490492
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=

internal/bootstrap/app_bootstrap.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"github.com/gin-gonic/gin"
2020
"github.com/steveiliop56/ding"
21+
"go.uber.org/dig"
2122

2223
"github.com/tinyauthapp/tinyauth/internal/model"
2324
"github.com/tinyauthapp/tinyauth/internal/repository"
@@ -56,6 +57,7 @@ type BootstrapApp struct {
5657
db *sql.DB
5758
ding *ding.Ding
5859
listeners []Listener
60+
dig *dig.Container
5961
}
6062

6163
func NewBootstrapApp(config model.Config) *BootstrapApp {
@@ -70,7 +72,11 @@ func (app *BootstrapApp) Setup() error {
7072
app.ctx = ctx
7173
app.cancel = cancel
7274

73-
// Create a ding instance
75+
// create the dig container
76+
c := dig.New()
77+
app.dig = c
78+
79+
// create a ding instance
7480
dg := ding.New(ctx)
7581
app.ding = dg
7682

@@ -157,12 +163,6 @@ func (app *BootstrapApp) Setup() error {
157163
app.runtime.OAuthProviders[id] = provider
158164
}
159165

160-
// setup oidc clients
161-
for id, client := range app.config.OIDC.Clients {
162-
client.ID = id
163-
app.runtime.OIDCClients = append(app.runtime.OIDCClients, client)
164-
}
165-
166166
// cookie domain
167167
cookieDomainResolver := utils.GetCookieDomain
168168

@@ -211,6 +211,33 @@ func (app *BootstrapApp) Setup() error {
211211
// store
212212
app.queries = store
213213

214+
// provide basic utilities to container
215+
type utilityProvider struct {
216+
dig.Out
217+
218+
Log *logger.Logger
219+
Config *model.Config
220+
Runtime *model.RuntimeConfig
221+
Ding *ding.Ding
222+
Ctx context.Context
223+
Queries repository.Store
224+
}
225+
226+
err = app.dig.Provide(func() utilityProvider {
227+
return utilityProvider{
228+
Log: app.log,
229+
Config: &app.config,
230+
Runtime: &app.runtime,
231+
Ding: app.ding,
232+
Ctx: app.ctx,
233+
Queries: app.queries,
234+
}
235+
})
236+
237+
if err != nil {
238+
return fmt.Errorf("failed to provide utilities to container: %w", err)
239+
}
240+
214241
// services
215242
err = app.setupServices()
216243

internal/bootstrap/router_bootstrap.go

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/tinyauthapp/tinyauth/internal/controller"
1414
"github.com/tinyauthapp/tinyauth/internal/middleware"
1515
"github.com/tinyauthapp/tinyauth/internal/model"
16+
"go.uber.org/dig"
1617

1718
"github.com/gin-gonic/gin"
1819
)
@@ -40,31 +41,94 @@ func (app *BootstrapApp) setupRouter() error {
4041
}
4142
}
4243

43-
contextMiddleware := middleware.NewContextMiddleware(app.log, app.runtime, app.services.authService, app.services.oauthBrokerService, app.services.tailscaleService)
44-
engine.Use(contextMiddleware.Middleware())
44+
middlewareProvideFor := []any{
45+
middleware.NewContextMiddleware,
46+
middleware.NewUIMiddleware,
47+
middleware.NewZerologMiddleware,
48+
}
4549

46-
uiMiddleware, err := middleware.NewUIMiddleware()
50+
for _, provider := range middlewareProvideFor {
51+
err := app.dig.Provide(provider)
52+
53+
if err != nil {
54+
return fmt.Errorf("failed to provide middleware: %w", err)
55+
}
56+
}
57+
58+
type middlewareInput struct {
59+
dig.In
60+
61+
ContextMiddleware *middleware.ContextMiddleware
62+
UIMiddleware *middleware.UIMiddleware
63+
ZerologMiddleware *middleware.ZerologMiddleware
64+
}
65+
66+
err := app.dig.Invoke(func(mi middlewareInput) {
67+
engine.Use(mi.ContextMiddleware.Middleware())
68+
engine.Use(mi.UIMiddleware.Middleware())
69+
engine.Use(mi.ZerologMiddleware.Middleware())
70+
})
4771

4872
if err != nil {
49-
return fmt.Errorf("failed to initialize UI middleware: %w", err)
73+
return fmt.Errorf("failed to invoke middleware: %w", err)
5074
}
5175

52-
engine.Use(uiMiddleware.Middleware())
76+
err = app.dig.Provide(func() *gin.RouterGroup {
77+
return &engine.RouterGroup
78+
}, dig.Name("mainRouterGroup"))
5379

54-
zerologMiddleware := middleware.NewZerologMiddleware(app.log)
80+
if err != nil {
81+
return fmt.Errorf("failed to provide main router group: %w", err)
82+
}
5583

56-
engine.Use(zerologMiddleware.Middleware())
84+
err = app.dig.Provide(func() *gin.RouterGroup {
85+
return engine.Group("/api")
86+
}, dig.Name("apiRouterGroup"))
5787

58-
apiRouter := engine.Group("/api")
88+
if err != nil {
89+
return fmt.Errorf("failed to provide api router group: %w", err)
90+
}
5991

60-
controller.NewContextController(app.log, app.config, app.runtime, apiRouter)
61-
controller.NewOAuthController(app.log, app.config, app.runtime, apiRouter, app.services.authService)
62-
controller.NewOIDCController(app.log, app.services.oidcService, app.runtime, apiRouter, &engine.RouterGroup)
63-
controller.NewProxyController(app.log, app.runtime, apiRouter, app.services.accessControlService, app.services.authService, app.services.policyEngine)
64-
controller.NewUserController(app.log, app.runtime, apiRouter, app.services.authService)
65-
controller.NewResourcesController(app.config, &engine.RouterGroup)
66-
controller.NewHealthController(apiRouter)
67-
controller.NewWellKnownController(app.services.oidcService, &engine.RouterGroup)
92+
controllerProvideFor := []any{
93+
controller.NewContextController,
94+
controller.NewOAuthController,
95+
controller.NewOIDCController,
96+
controller.NewProxyController,
97+
controller.NewUserController,
98+
controller.NewResourcesController,
99+
controller.NewHealthController,
100+
controller.NewWellKnownController,
101+
}
102+
103+
for _, provider := range controllerProvideFor {
104+
err := app.dig.Provide(provider)
105+
106+
if err != nil {
107+
return fmt.Errorf("failed to provide controller: %w", err)
108+
}
109+
}
110+
111+
type controllerInput struct {
112+
dig.In
113+
114+
ContextController *controller.ContextController
115+
OAuthController *controller.OAuthController
116+
OIDCController *controller.OIDCController
117+
ProxyController *controller.ProxyController
118+
UserController *controller.UserController
119+
ResourcesController *controller.ResourcesController
120+
HealthController *controller.HealthController
121+
WellKnownController *controller.WellKnownController
122+
}
123+
124+
// force dig to build all controllers and register their routes
125+
err = app.dig.Invoke(func(ci controllerInput) error {
126+
return nil
127+
})
128+
129+
if err != nil {
130+
return fmt.Errorf("failed to invoke controllers: %w", err)
131+
}
68132

69133
app.router = engine
70134
return nil

0 commit comments

Comments
 (0)