registry.go raw
1 //go:build !(js && wasm)
2
3 package acl
4
5 import (
6 "context"
7 "sort"
8 "sync"
9
10 "next.orly.dev/pkg/lol/errorf"
11 "next.orly.dev/pkg/database"
12 )
13
14 // DriverFactory is the signature for ACL driver factory functions.
15 type DriverFactory func(ctx context.Context, db database.Database, cfg *DriverConfig) (I, error)
16
17 // DriverConfig holds configuration for ACL drivers.
18 type DriverConfig struct {
19 // Common settings
20 LogLevel string
21 Owners []string
22 Admins []string
23 BootstrapRelays []string
24 RelayAddresses []string
25
26 // Follows-specific settings
27 FollowListFrequency string
28 FollowsThrottleEnabled bool
29 FollowsThrottlePerEvent string
30 FollowsThrottleMaxDelay string
31 }
32
33 // DriverInfo contains metadata about a registered ACL driver.
34 type DriverInfo struct {
35 Name string
36 Description string
37 Factory DriverFactory
38 }
39
40 // I is the ACL interface that drivers must implement.
41 // This is re-exported from the interfaces package for convenience.
42 type I interface {
43 Configure(cfg ...any) (err error)
44 GetAccessLevel(pub []byte, address string) (level string)
45 GetACLInfo() (name, description, documentation string)
46 Syncer()
47 Type() string
48 }
49
50 var (
51 driversMu sync.RWMutex
52 drivers = make(map[string]*DriverInfo)
53 )
54
55 // RegisterDriver registers an ACL driver with the given name and factory.
56 // This is typically called from init() in the driver package.
57 func RegisterDriver(name, description string, factory DriverFactory) {
58 driversMu.Lock()
59 defer driversMu.Unlock()
60 drivers[name] = &DriverInfo{
61 Name: name,
62 Description: description,
63 Factory: factory,
64 }
65 }
66
67 // GetDriver returns the factory for the named driver, or nil if not found.
68 func GetDriver(name string) DriverFactory {
69 driversMu.RLock()
70 defer driversMu.RUnlock()
71 if info, ok := drivers[name]; ok {
72 return info.Factory
73 }
74 return nil
75 }
76
77 // HasDriver returns true if the named driver is registered.
78 func HasDriver(name string) bool {
79 driversMu.RLock()
80 defer driversMu.RUnlock()
81 _, ok := drivers[name]
82 return ok
83 }
84
85 // ListDrivers returns a sorted list of registered driver names.
86 func ListDrivers() []string {
87 driversMu.RLock()
88 defer driversMu.RUnlock()
89 names := make([]string, 0, len(drivers))
90 for name := range drivers {
91 names = append(names, name)
92 }
93 sort.Strings(names)
94 return names
95 }
96
97 // ListDriversWithInfo returns information about all registered drivers.
98 func ListDriversWithInfo() []*DriverInfo {
99 driversMu.RLock()
100 defer driversMu.RUnlock()
101 infos := make([]*DriverInfo, 0, len(drivers))
102 for _, info := range drivers {
103 infos = append(infos, info)
104 }
105 // Sort by name for consistent output
106 sort.Slice(infos, func(i, j int) bool {
107 return infos[i].Name < infos[j].Name
108 })
109 return infos
110 }
111
112 // NewFromDriver creates an ACL using the named driver.
113 // Returns an error if the driver is not registered.
114 func NewFromDriver(ctx context.Context, driverName string, db database.Database, cfg *DriverConfig) (I, error) {
115 factory := GetDriver(driverName)
116 if factory == nil {
117 return nil, errorf.E("ACL driver %q not available; registered: %v", driverName, ListDrivers())
118 }
119 return factory(ctx, db, cfg)
120 }
121