package centrifugo_test import ( "context" "fmt" "net/http" "net/http/httptest" "strings" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" "git.golem15.com/golem15/summercms/modules/lighthouse" "git.golem15.com/golem15/summercms/modules/lighthouse/centrifugo" "git.golem15.com/golem15/summercms/modules/surf" ) // newApp returns an app whose config selects a realtime driver. func newApp(settings map[string]any) (*backpack.App, error) { cfg, err := compass.Open(compass.Options{Dir: "config", Env: "development", Environ: []string{}}) if err != nil { return nil, err } for k, v := range settings { if err := cfg.Set(k, v); err != nil { return nil, err } } return backpack.New(cfg), nil } func ExampleProxyHandler() { svc, err := lighthouse.From(backpack.New(nil)) if err != nil { fmt.Println(err) return } // Members of blog 7 may subscribe to its channels. err = svc.Registry().Register("blog", lighthouse.AuthorizerFunc( func(ctx context.Context, userID uint, channel string) lighthouse.Result { if userID == 42 && lighthouse.ChannelID(channel) == 7 { return lighthouse.Allowed(nil) } return lighthouse.Denied("not a member of the blog") })) if err != nil { fmt.Println(err) return } // realtime.centrifugo.proxy_secret; set it through the environment. proxy := centrifugo.ProxyHandler(svc, centrifugo.Config{ProxySecret: "test-only-proxy-secret"}) // What Centrifugo posts to the subscribe proxy. subscribe := func(secret, user, channel string) { body := fmt.Sprintf(`{"client":"c1","user":%q,"channel":%q}`, user, channel) req := httptest.NewRequest(http.MethodPost, "/api/realtime/subscribe", strings.NewReader(body)) req.Header.Set("X-Centrifugo-Secret", secret) rec := httptest.NewRecorder() proxy.ServeHTTP(rec, req) fmt.Println(rec.Code, strings.TrimSpace(rec.Body.String())) } subscribe("test-only-proxy-secret", "42", "blog:7") subscribe("test-only-proxy-secret", "5", "blog:7") subscribe("wrong-secret", "42", "blog:7") // Output: // 200 {"result":{"info":[]}} // 200 {"error":{"code":403,"message":"Access denied"}} // 200 {"error":{"code":403,"message":"Access denied"}} } func ExampleDriver_Routes() { app, err := newApp(map[string]any{"realtime.driver": "centrifugo"}) if err != nil { fmt.Println(err) return } svc, err := lighthouse.From(app) if err != nil { fmt.Println(err) return } // In a plugin's Routes method, r is the router the plugin receives. r := surf.New(nil) err = lighthouse.Mount(r, svc.Driver(), lighthouse.Surfaces{ UserAuth: surf.Use("acme.auth"), Middleware: surf.Use("throttle:60,1"), }) if err != nil { fmt.Println(err) return } for _, rt := range r.Routes() { fmt.Println(rt.Method, rt.Pattern, rt.Middleware, "raw:", rt.Raw) } // A user route without a guard is refused. err = lighthouse.Mount(surf.New(nil), svc.Driver(), lighthouse.Surfaces{}) fmt.Println(err != nil) // Output: // GET /api/realtime/token [acme.auth throttle:60,1] raw: false // POST /api/realtime/subscribe [throttle:60,1] raw: true // true }