-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoption.go
More file actions
329 lines (287 loc) · 8.93 KB
/
Copy pathoption.go
File metadata and controls
329 lines (287 loc) · 8.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
package authsome
import (
log "github.com/xraph/go-utils/log"
"github.com/xraph/authsome/account"
"github.com/xraph/authsome/appsessionconfig"
"github.com/xraph/authsome/bridge"
"github.com/xraph/authsome/bridge/keysmithadapter"
"github.com/xraph/authsome/bridge/ledgeradapter"
"github.com/xraph/authsome/bridge/wardenadapter"
"github.com/xraph/authsome/ceremony"
"github.com/xraph/authsome/lockout"
"github.com/xraph/authsome/plugin"
"github.com/xraph/authsome/ratelimit"
"github.com/xraph/authsome/securityevent"
"github.com/xraph/authsome/store"
"github.com/xraph/authsome/strategy"
"github.com/xraph/authsome/tokenformat"
"github.com/xraph/grove"
"github.com/xraph/keysmith"
xledger "github.com/xraph/ledger"
"github.com/xraph/warden"
)
// Option configures the AuthSome engine.
type Option func(*Engine)
// WithConfig sets the engine configuration.
func WithConfig(cfg Config) Option {
return func(e *Engine) {
e.config = cfg
}
}
// WithStore sets the persistence backend.
func WithStore(s store.Store) Option {
return func(e *Engine) {
e.store = s
}
}
// WithLogger sets the structured logger.
func WithLogger(logger log.Logger) Option {
return func(e *Engine) {
e.logger = logger
}
}
// WithDebug enables verbose debug logging.
func WithDebug(debug bool) Option {
return func(e *Engine) {
e.config.Debug = debug
}
}
// WithAppID sets the application identity used in forge.Scope.
func WithAppID(appID string) Option {
return func(e *Engine) {
e.config.AppID = appID
}
}
// WithPlugin registers a plugin with the engine.
func WithPlugin(p plugin.Plugin) Option {
return func(e *Engine) {
e.pendingPlugins = append(e.pendingPlugins, p)
}
}
// WithStrategy registers an authentication strategy with the given priority.
// Lower priority values are evaluated first.
func WithStrategy(s strategy.Strategy, priority int) Option {
return func(e *Engine) {
e.pendingStrategies = append(e.pendingStrategies, pendingStrategy{s, priority})
}
}
// WithChronicle sets the audit trail bridge.
func WithChronicle(c bridge.Chronicle) Option {
return func(e *Engine) {
e.chronicle = c
}
}
// WithAuthorizer sets the authorization bridge.
func WithAuthorizer(a bridge.Authorizer) Option {
return func(e *Engine) {
e.authorizer = a
}
}
// WithWarden sets the required Warden authorization engine. All RBAC operations
// (roles, permissions, assignments, and permission checks) delegate to Warden's
// full RBAC+ReBAC+ABAC evaluation. Warden is required — NewEngine will return
// an error if this option is not provided.
// This also sets the bridge.Authorizer for backward compatibility.
func WithWarden(w *warden.Engine) Option {
return func(e *Engine) {
e.wardenEng = w
e.authorizer = wardenadapter.New(w)
}
}
// WithKeysmith sets the first-class Keysmith key management engine. When set,
// API key operations delegate to Keysmith (gaining rate limiting, policy
// enforcement, key rotation with grace periods, scope management, usage
// tracking, and multi-tenant support).
// This also sets the bridge.KeyManager for backward compatibility.
func WithKeysmith(ks *keysmith.Engine) Option {
return func(e *Engine) {
e.keysmithEng = ks
e.keyManager = keysmithadapter.New(ks)
}
}
// WithKeyManager sets the key management bridge.
func WithKeyManager(km bridge.KeyManager) Option {
return func(e *Engine) {
e.keyManager = km
}
}
// WithEventRelay sets the webhook/event relay bridge.
func WithEventRelay(r bridge.EventRelay) Option {
return func(e *Engine) {
e.relay = r
}
}
// WithMailer sets the transactional email bridge.
func WithMailer(m bridge.Mailer) Option {
return func(e *Engine) {
e.mailer = m
}
}
// WithSMSSender sets the SMS sending bridge for MFA verification codes.
func WithSMSSender(s bridge.SMSSender) Option {
return func(e *Engine) {
e.sms = s
}
}
// WithHerald sets the unified notification system bridge.
// When configured, Herald replaces the separate Mailer and SMSSender bridges
// for notification delivery, providing multi-channel support with templates,
// scoped configuration, and user preference management.
func WithHerald(h bridge.Herald) Option {
return func(e *Engine) {
e.heraldBridge = h
}
}
// WithTokenEncryptor sets the at-rest Encryptor used for sensitive opaque
// payloads (third-party OAuth access/refresh tokens, etc). When not set,
// the engine reads AUTHSOME_TOKEN_ENCRYPTION_KEY from the environment;
// if that is also unset, it falls back to a NoopEncryptor with a warning.
func WithTokenEncryptor(enc bridge.Encryptor) Option {
return func(e *Engine) {
e.tokenEncryptor = enc
}
}
// WithVault sets the secrets, feature flags, and configuration bridge.
func WithVault(v bridge.Vault) Option {
return func(e *Engine) {
e.vault = v
}
}
// WithDispatcher sets the background job queue bridge.
func WithDispatcher(d bridge.Dispatcher) Option {
return func(e *Engine) {
e.dispatcher = d
}
}
// WithLedger sets the billing/metering bridge.
func WithLedger(l bridge.Ledger) Option {
return func(e *Engine) {
e.ledger = l
}
}
// WithLedgerEngine sets the first-class Ledger billing engine. When set,
// the subscription plugin can access the ledger store directly for list
// operations (plans, features, subscriptions). This also sets the
// bridge.Ledger adapter for backward compatibility.
func WithLedgerEngine(l *xledger.Ledger) Option {
return func(e *Engine) {
e.ledgerEng = l
e.ledger = ledgeradapter.New(l)
}
}
// WithBasePath sets the URL prefix for all auth routes.
func WithBasePath(path string) Option {
return func(e *Engine) {
e.config.BasePath = path
}
}
// WithDisableRoutes prevents automatic route registration.
func WithDisableRoutes() Option {
return func(e *Engine) {
e.config.DisableRoutes = true
}
}
// WithDisableMigrate prevents automatic migration on Start.
func WithDisableMigrate() Option {
return func(e *Engine) {
e.config.DisableMigrate = true
}
}
// WithDriverName sets the grove driver name for plugin migration discovery.
func WithDriverName(name string) Option {
return func(e *Engine) {
e.config.DriverName = name
}
}
// WithDB stores the grove database handle so plugins can create their
// own persistent stores via Engine.DB().
func WithDB(db *grove.DB) Option {
return func(e *Engine) {
e.db = db
}
}
// WithRateLimiter sets the rate limiter for brute-force protection.
func WithRateLimiter(rl ratelimit.Limiter) Option {
return func(e *Engine) {
e.rateLimiter = rl
}
}
// WithLockoutTracker sets the account lockout tracker.
func WithLockoutTracker(t lockout.Tracker) Option {
return func(e *Engine) {
e.lockout = t
}
}
// WithLockoutConfig sets the lockout configuration.
func WithLockoutConfig(cfg LockoutConfig) Option {
return func(e *Engine) {
e.config.Lockout = cfg
}
}
// WithMetrics sets the metrics collector for observability.
func WithMetrics(m bridge.MetricsCollector) Option {
return func(e *Engine) {
e.metrics = m
}
}
// WithCeremonyStore sets the ceremony state store for short-lived auth
// ceremony sessions (passkey, social OAuth, SSO, MFA SMS challenges).
// When not set, plugins fall back to an in-memory store.
func WithCeremonyStore(s ceremony.Store) Option {
return func(e *Engine) {
e.ceremonyStore = s
}
}
// WithPasswordHistory sets the password history store for preventing
// password reuse. Works in conjunction with PasswordConfig.HistoryCount.
func WithPasswordHistory(s account.PasswordHistoryStore) Option {
return func(e *Engine) {
e.passwordHistory = s
}
}
// WithSecurityEvents sets the security event store for persisting and
// querying security-relevant events (failed logins, lockouts, etc.).
func WithSecurityEvents(s securityevent.Store) Option {
return func(e *Engine) {
e.securityEvents = s
}
}
// WithAppSessionConfig registers a per-app session configuration override.
// The config is seeded into the store during engine Start and overrides the
// global session config for sessions created under the specified app.
func WithAppSessionConfig(cfg *appsessionconfig.Config) Option {
return func(e *Engine) {
e.pendingAppSessCfgs = append(e.pendingAppSessCfgs, cfg)
}
}
// WithDefaultTokenFormat sets the default token format for access tokens.
// When not set, opaque tokens (64-char hex) are used.
func WithDefaultTokenFormat(f tokenformat.Format) Option {
return func(e *Engine) {
e.defaultTokenFormat = f
}
}
// WithJWTFormat registers a JWT token format for a specific app.
// Access tokens for this app will be signed JWTs instead of opaque tokens.
func WithJWTFormat(appID string, jwtFmt *tokenformat.JWT) Option {
return func(e *Engine) {
if e.jwtFormats == nil {
e.jwtFormats = make(map[string]*tokenformat.JWT)
}
e.jwtFormats[appID] = jwtFmt
}
}
// WithBootstrap enables automatic platform app bootstrap with optional customization.
func WithBootstrap(opts ...BootstrapOption) Option {
return func(e *Engine) {
cfg := DefaultBootstrapConfig()
for _, opt := range opts {
opt(cfg)
}
e.bootstrapCfg = cfg
}
}
type pendingStrategy struct {
strategy strategy.Strategy
priority int
}