From 38ee1f579e311da5f75ffdc4057995feb22fcb79 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Fri, 23 Dec 2022 13:45:58 +0100 Subject: [PATCH] extract sse into own hub service --- go.mod | 2 + go.sum | 7 ++- ocis-pkg/config/config.go | 2 + ocis-pkg/config/defaultconfig.go | 2 + ocis/pkg/command/hub.go | 30 ++++++++++ ocis/pkg/runtime/service/service.go | 2 + services/hub/cmd/hub/main.go | 13 +++++ services/hub/pkg/command/root.go | 52 ++++++++++++++++++ services/hub/pkg/command/server.go | 55 +++++++++++++++++++ services/hub/pkg/config/config.go | 32 +++++++++++ .../hub/pkg/config/defaults/defaultconfig.go | 37 +++++++++++++ services/hub/pkg/config/parser/parse.go | 42 ++++++++++++++ services/hub/pkg/service/service.go | 40 ++++++++++++++ services/hub/pkg/service/sse.go | 38 +++++++++++++ .../pkg/config/defaults/defaultconfig.go | 4 ++ 15 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 ocis/pkg/command/hub.go create mode 100644 services/hub/cmd/hub/main.go create mode 100644 services/hub/pkg/command/root.go create mode 100644 services/hub/pkg/command/server.go create mode 100644 services/hub/pkg/config/config.go create mode 100644 services/hub/pkg/config/defaults/defaultconfig.go create mode 100644 services/hub/pkg/config/parser/parse.go create mode 100644 services/hub/pkg/service/service.go create mode 100644 services/hub/pkg/service/sse.go diff --git a/go.mod b/go.mod index 9c3f644ec96..5d06797a49e 100644 --- a/go.mod +++ b/go.mod @@ -71,6 +71,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.9 github.com/prometheus/client_golang v1.14.0 + github.com/r3labs/sse/v2 v2.9.0 github.com/rogpeppe/go-internal v1.9.0 github.com/rs/zerolog v1.29.0 github.com/shamaton/msgpack/v2 v2.1.1 @@ -312,6 +313,7 @@ require ( golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect + gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect diff --git a/go.sum b/go.sum index e87613ad01d..cb39a48e7c8 100644 --- a/go.sum +++ b/go.sum @@ -625,8 +625,6 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4= github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc= github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= -github.com/cs3org/reva/v2 v2.12.1-0.20230330074121-1f0e39b47ee7 h1:iwNv/IBHh9UsBj79WwM10z4NOau6T6x/jyUr2AsETjs= -github.com/cs3org/reva/v2 v2.12.1-0.20230330074121-1f0e39b47ee7/go.mod h1:FNAYs5H3xs8v0OFmNgZtiMAzIMXd/6TJmO0uZuNn8pQ= github.com/cs3org/reva/v2 v2.12.1-0.20230331184913-eca8953fb6e9 h1:zUMD0UvKVPbR3UaodnA0GXuBycxrIuaO8Kshgi3iKKI= github.com/cs3org/reva/v2 v2.12.1-0.20230331184913-eca8953fb6e9/go.mod h1:FNAYs5H3xs8v0OFmNgZtiMAzIMXd/6TJmO0uZuNn8pQ= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= @@ -1463,6 +1461,8 @@ github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9 github.com/prometheus/statsd_exporter v0.22.8 h1:Qo2D9ZzaQG+id9i5NYNGmbf1aa/KxKbB9aKfMS+Yib0= github.com/prometheus/statsd_exporter v0.22.8/go.mod h1:/DzwbTEaFTE0Ojz5PqcSk6+PFHOPWGxdXVr6yC8eFOM= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/r3labs/sse/v2 v2.9.0 h1:CxP+H0CBm3VCEJtrHxASzzCsS+DoQC0WVep648+os3A= +github.com/r3labs/sse/v2 v2.9.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= @@ -1793,6 +1793,7 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -2363,6 +2364,8 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= +gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/ocis-pkg/config/config.go b/ocis-pkg/config/config.go index 7d71a792da2..ff57992ab55 100644 --- a/ocis-pkg/config/config.go +++ b/ocis-pkg/config/config.go @@ -14,6 +14,7 @@ import ( gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/config" graph "github.com/owncloud/ocis/v2/services/graph/pkg/config" groups "github.com/owncloud/ocis/v2/services/groups/pkg/config" + hub "github.com/owncloud/ocis/v2/services/hub/pkg/config" idm "github.com/owncloud/ocis/v2/services/idm/pkg/config" idp "github.com/owncloud/ocis/v2/services/idp/pkg/config" invitations "github.com/owncloud/ocis/v2/services/invitations/pkg/config" @@ -97,6 +98,7 @@ type Config struct { Policies *policies.Config `yaml:"policies"` Proxy *proxy.Config `yaml:"proxy"` Settings *settings.Config `yaml:"settings"` + Hub *hub.Config `yaml:"settings"` Sharing *sharing.Config `yaml:"sharing"` StorageSystem *storagesystem.Config `yaml:"storage_system"` StoragePublicLink *storagepublic.Config `yaml:"storage_public"` diff --git a/ocis-pkg/config/defaultconfig.go b/ocis-pkg/config/defaultconfig.go index 3afd0896c8a..0b719654c2b 100644 --- a/ocis-pkg/config/defaultconfig.go +++ b/ocis-pkg/config/defaultconfig.go @@ -13,6 +13,7 @@ import ( gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/config/defaults" graph "github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults" groups "github.com/owncloud/ocis/v2/services/groups/pkg/config/defaults" + hub "github.com/owncloud/ocis/v2/services/hub/pkg/config/defaults" idm "github.com/owncloud/ocis/v2/services/idm/pkg/config/defaults" idp "github.com/owncloud/ocis/v2/services/idp/pkg/config/defaults" invitations "github.com/owncloud/ocis/v2/services/invitations/pkg/config/defaults" @@ -59,6 +60,7 @@ func DefaultConfig() *Config { Gateway: gateway.DefaultConfig(), Graph: graph.DefaultConfig(), Groups: groups.DefaultConfig(), + Hub: hub.DefaultConfig(), IDM: idm.DefaultConfig(), IDP: idp.DefaultConfig(), Invitations: invitations.DefaultConfig(), diff --git a/ocis/pkg/command/hub.go b/ocis/pkg/command/hub.go new file mode 100644 index 00000000000..5bde00a1308 --- /dev/null +++ b/ocis/pkg/command/hub.go @@ -0,0 +1,30 @@ +package command + +import ( + "github.com/owncloud/ocis/v2/ocis-pkg/config" + "github.com/owncloud/ocis/v2/ocis-pkg/config/configlog" + "github.com/owncloud/ocis/v2/ocis-pkg/config/parser" + "github.com/owncloud/ocis/v2/ocis/pkg/command/helper" + "github.com/owncloud/ocis/v2/ocis/pkg/register" + "github.com/owncloud/ocis/v2/services/hub/pkg/command" + "github.com/urfave/cli/v2" +) + +// HubCommand is the entrypoint for the web command. +func HubCommand(cfg *config.Config) *cli.Command { + return &cli.Command{ + Name: cfg.Hub.Service.Name, + Usage: helper.SubcommandDescription(cfg.Hub.Service.Name), + Category: "services", + Before: func(c *cli.Context) error { + configlog.Error(parser.ParseConfig(cfg, true)) + cfg.WebDAV.Commons = cfg.Commons + return nil + }, + Subcommands: command.GetCommands(cfg.Hub), + } +} + +func init() { + register.AddCommand(HubCommand) +} diff --git a/ocis/pkg/runtime/service/service.go b/ocis/pkg/runtime/service/service.go index 06cc367ed94..1cb5b981f9a 100644 --- a/ocis/pkg/runtime/service/service.go +++ b/ocis/pkg/runtime/service/service.go @@ -27,6 +27,7 @@ import ( gateway "github.com/owncloud/ocis/v2/services/gateway/pkg/command" graph "github.com/owncloud/ocis/v2/services/graph/pkg/command" groups "github.com/owncloud/ocis/v2/services/groups/pkg/command" + hub "github.com/owncloud/ocis/v2/services/hub/pkg/command" idm "github.com/owncloud/ocis/v2/services/idm/pkg/command" idp "github.com/owncloud/ocis/v2/services/idp/pkg/command" invitations "github.com/owncloud/ocis/v2/services/invitations/pkg/command" @@ -133,6 +134,7 @@ func NewService(options ...Option) (*Service, error) { s.ServicesRegistry[opts.Config.Postprocessing.Service.Name] = postprocessing.NewSutureService s.ServicesRegistry[opts.Config.EventHistory.Service.Name] = eventhistory.NewSutureService s.ServicesRegistry[opts.Config.Userlog.Service.Name] = userlog.NewSutureService + s.ServicesRegistry[opts.Config.Hub.Service.Name] = hub.NewSutureService // populate delayed services s.Delayed[opts.Config.Sharing.Service.Name] = sharing.NewSutureService diff --git a/services/hub/cmd/hub/main.go b/services/hub/cmd/hub/main.go new file mode 100644 index 00000000000..3a79b3cc2b4 --- /dev/null +++ b/services/hub/cmd/hub/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "github.com/owncloud/ocis/v2/services/hub/pkg/command" + "github.com/owncloud/ocis/v2/services/hub/pkg/config/defaults" + "os" +) + +func main() { + if err := command.Execute(defaults.DefaultConfig()); err != nil { + os.Exit(1) + } +} diff --git a/services/hub/pkg/command/root.go b/services/hub/pkg/command/root.go new file mode 100644 index 00000000000..d2cb7ac395a --- /dev/null +++ b/services/hub/pkg/command/root.go @@ -0,0 +1,52 @@ +package command + +import ( + "context" + ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config" + "github.com/owncloud/ocis/v2/services/hub/pkg/config" + "os" + + "github.com/owncloud/ocis/v2/ocis-pkg/clihelper" + "github.com/thejerf/suture/v4" + "github.com/urfave/cli/v2" +) + +// GetCommands provides all commands for this service +func GetCommands(cfg *config.Config) cli.Commands { + return []*cli.Command{ + Server(cfg), + } +} + +// Execute is the entry point for the web command. +func Execute(cfg *config.Config) error { + app := clihelper.DefaultApp(&cli.App{ + Name: "hub", + Usage: "Serve ownCloud hub for oCIS", + Commands: GetCommands(cfg), + }) + + return app.Run(os.Args) +} + +// SutureService allows for the web command to be embedded and supervised by a suture supervisor tree. +type SutureService struct { + cfg *config.Config +} + +// NewSutureService creates a new web.SutureService +func NewSutureService(cfg *ociscfg.Config) suture.Service { + cfg.Hub.Commons = cfg.Commons + return SutureService{ + cfg: cfg.Hub, + } +} + +func (s SutureService) Serve(ctx context.Context) error { + s.cfg.Context = ctx + if err := Execute(s.cfg); err != nil { + return err + } + + return nil +} diff --git a/services/hub/pkg/command/server.go b/services/hub/pkg/command/server.go new file mode 100644 index 00000000000..01ad8212a5b --- /dev/null +++ b/services/hub/pkg/command/server.go @@ -0,0 +1,55 @@ +package command + +import ( + "context" + "fmt" + "github.com/owncloud/ocis/v2/ocis-pkg/config/configlog" + "github.com/owncloud/ocis/v2/ocis-pkg/service/http" + "github.com/owncloud/ocis/v2/ocis-pkg/version" + "github.com/owncloud/ocis/v2/services/hub/pkg/config" + "github.com/owncloud/ocis/v2/services/hub/pkg/config/parser" + "github.com/owncloud/ocis/v2/services/hub/pkg/service" + "github.com/urfave/cli/v2" + "go-micro.dev/v4" +) + +// Server is the entrypoint for the server command. +func Server(cfg *config.Config) *cli.Command { + return &cli.Command{ + Name: "server", + Usage: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", "hub"), + Category: "server", + Before: func(c *cli.Context) error { + return configlog.ReturnFatal(parser.ParseConfig(cfg)) + }, + Action: func(c *cli.Context) error { + var ( + ctx, cancel = func() (context.Context, context.CancelFunc) { + if cfg.Context == nil { + return context.WithCancel(context.Background()) + } + return context.WithCancel(cfg.Context) + }() + ) + + defer cancel() + + httpService, err := http.NewService( + http.Name(cfg.Service.Name), + http.Namespace(cfg.HTTP.Namespace), + http.Version(version.GetString()), + http.Address(cfg.HTTP.Addr), + http.Context(ctx), + ) + if err != nil { + return err + } + + if err := micro.RegisterHandler(httpService.Server(), service.New(cfg)); err != nil { + return err + } + + return httpService.Run() + }, + } +} diff --git a/services/hub/pkg/config/config.go b/services/hub/pkg/config/config.go new file mode 100644 index 00000000000..97a15266a81 --- /dev/null +++ b/services/hub/pkg/config/config.go @@ -0,0 +1,32 @@ +package config + +import ( + "context" + "github.com/owncloud/ocis/v2/ocis-pkg/shared" +) + +// Config combines all available configuration parts. +type Config struct { + Commons *shared.Commons `yaml:"-"` // don't use this directly as configuration for a service + HTTP HTTP `yaml:"http"` + Service Service `yaml:"-"` + TokenManager *TokenManager `yaml:"token_manager"` + Context context.Context `yaml:"-"` +} + +// Service defines the available service configuration. +type Service struct { + Name string `yaml:"-"` +} + +// HTTP defines the available http configuration. +type HTTP struct { + Addr string `yaml:"addr" env:"HUB_HTTP_ADDR" desc:"The bind address of the HTTP service."` + Namespace string `yaml:"-"` + Root string `yaml:"root" env:"HUB_HTTP_ROOT" desc:"Subdirectory that serves as the root for this HTTP service."` +} + +// TokenManager is the config for using the reva token manager +type TokenManager struct { + JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;HUB_JWT_SECRET" desc:"The secret to mint and validate jwt tokens."` +} diff --git a/services/hub/pkg/config/defaults/defaultconfig.go b/services/hub/pkg/config/defaults/defaultconfig.go new file mode 100644 index 00000000000..1bbb1dcf2e4 --- /dev/null +++ b/services/hub/pkg/config/defaults/defaultconfig.go @@ -0,0 +1,37 @@ +package defaults + +import ( + "github.com/owncloud/ocis/v2/services/hub/pkg/config" + "strings" +) + +// DefaultConfig returns the default config +func DefaultConfig() *config.Config { + return &config.Config{ + Service: config.Service{ + Name: "hub", + }, + HTTP: config.HTTP{ + Addr: "127.0.0.1:9180", + Namespace: "com.owncloud.web", + Root: "/", + }, + } +} + +func EnsureDefaults(cfg *config.Config) { + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { + cfg.TokenManager = &config.TokenManager{ + JWTSecret: cfg.Commons.TokenManager.JWTSecret, + } + } else if cfg.TokenManager == nil { + cfg.TokenManager = &config.TokenManager{} + } +} + +func Sanitize(cfg *config.Config) { + // sanitize config + if cfg.HTTP.Root != "/" { + cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/") + } +} diff --git a/services/hub/pkg/config/parser/parse.go b/services/hub/pkg/config/parser/parse.go new file mode 100644 index 00000000000..2337017bd9e --- /dev/null +++ b/services/hub/pkg/config/parser/parse.go @@ -0,0 +1,42 @@ +package parser + +import ( + "errors" + + ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config" + "github.com/owncloud/ocis/v2/ocis-pkg/shared" + "github.com/owncloud/ocis/v2/services/hub/pkg/config" + "github.com/owncloud/ocis/v2/services/hub/pkg/config/defaults" + + "github.com/owncloud/ocis/v2/ocis-pkg/config/envdecode" +) + +// ParseConfig loads configuration from known paths. +func ParseConfig(cfg *config.Config) error { + _, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg) + if err != nil { + return err + } + + defaults.EnsureDefaults(cfg) + + // load all env variables relevant to the config in the current context. + if err := envdecode.Decode(cfg); err != nil { + // no environment variable set for this config is an expected "error" + if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) { + return err + } + } + + defaults.Sanitize(cfg) + + return Validate(cfg) +} + +func Validate(cfg *config.Config) error { + if cfg.TokenManager.JWTSecret == "" { + return shared.MissingJWTTokenError(cfg.Service.Name) + } + + return nil +} diff --git a/services/hub/pkg/service/service.go b/services/hub/pkg/service/service.go new file mode 100644 index 00000000000..d7166329fa8 --- /dev/null +++ b/services/hub/pkg/service/service.go @@ -0,0 +1,40 @@ +package service + +import ( + "github.com/go-chi/chi/v5" + "github.com/owncloud/ocis/v2/ocis-pkg/account" + opkgm "github.com/owncloud/ocis/v2/ocis-pkg/middleware" + "github.com/owncloud/ocis/v2/services/hub/pkg/config" + "net/http" +) + +// Service defines the service handlers. + +type Service struct { + m *chi.Mux +} + +// New returns a service implementation for Service. +func New(cfg *config.Config) Service { + m := chi.NewMux() + m.Use( + opkgm.ExtractAccountUUID( + account.JWTSecret(cfg.TokenManager.JWTSecret), + ), + ) + + m.Route("/hub", func(r chi.Router) { + r.Route("/sse", ServeSSE) + }) + + svc := Service{ + m: m, + } + + return svc +} + +// ServeHTTP implements the Service interface. +func (s Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { + s.m.ServeHTTP(w, r) +} diff --git a/services/hub/pkg/service/sse.go b/services/hub/pkg/service/sse.go new file mode 100644 index 00000000000..335c79c9ef6 --- /dev/null +++ b/services/hub/pkg/service/sse.go @@ -0,0 +1,38 @@ +package service + +import ( + "fmt" + "github.com/cs3org/reva/v2/pkg/ctx" + "github.com/go-chi/chi/v5" + "github.com/r3labs/sse/v2" + "net/http" + "time" +) + +type SSE struct{} + +func ServeSSE(r chi.Router) { + server := sse.New() + stream := server.CreateStream("messages") + stream.AutoReplay = false + + r.Get("/", func(w http.ResponseWriter, r *http.Request) { + u, ok := ctx.ContextGetUser(r.Context()) + if !ok { + w.WriteHeader(http.StatusInternalServerError) + return + } + + go func() { + for range time.Tick(time.Second * 4) { + t := time.Now() + server.Publish("messages", &sse.Event{ + Data: []byte(fmt.Sprintf("[%s] Hello %s, new push notification from server!", t.Format("2006-01-02 15:04:05"), u.Username)), + }) + } + }() + + server.ServeHTTP(w, r) + }) + +} diff --git a/services/proxy/pkg/config/defaults/defaultconfig.go b/services/proxy/pkg/config/defaults/defaultconfig.go index 582dbd0da79..f38ca170c52 100644 --- a/services/proxy/pkg/config/defaults/defaultconfig.go +++ b/services/proxy/pkg/config/defaults/defaultconfig.go @@ -231,6 +231,10 @@ func DefaultPolicies() []config.Policy { Endpoint: "/api/v0/settings", Service: "com.owncloud.web.settings", }, + { + Endpoint: "/hub", + Service: "com.owncloud.web.hub", + }, }, }, }