From 159785a3b5362b6889e28d6b8222d1d09ff4f489 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 21 May 2026 23:26:20 +0200 Subject: [PATCH 1/6] enhancement: make collaboration font management functionality public --- .gitignore | 8 +- .../pkg/collaboration/collaboration.go | 39 ++ services/collaboration/pkg/command/server.go | 47 ++- services/collaboration/pkg/config/config.go | 1 + .../pkg/config/defaults/defaultconfig.go | 6 + services/collaboration/pkg/config/font.go | 6 + services/collaboration/pkg/font/service.go | 350 ++++++++++++++++++ .../collaboration/pkg/font/service_test.go | 224 +++++++++++ .../pkg/font/testdata/arimo-regular.png | Bin 0 -> 1326 bytes .../pkg/font/testdata/arimo-regular.ttf | Bin 0 -> 315784 bytes .../pkg/font/testdata/fontconfiguration.json | 22 ++ .../collaboration/pkg/font/testdata/props.txt | 1 + .../collaboration/pkg/server/http/option.go | 18 +- .../collaboration/pkg/server/http/server.go | 22 +- .../pkg/config/defaults/defaultconfig.go | 10 + .../proxy/pkg/middleware/authentication.go | 5 +- .../settings/pkg/store/defaults/defaults.go | 2 + .../pkg/store/defaults/permissions.go | 19 + services/web/Makefile | 12 +- services/web/pkg/apps/apps.go | 36 +- services/web/pkg/apps/apps_test.go | 16 +- services/web/pkg/service/v0/service.go | 7 +- 22 files changed, 813 insertions(+), 38 deletions(-) create mode 100644 services/collaboration/pkg/collaboration/collaboration.go create mode 100644 services/collaboration/pkg/config/font.go create mode 100644 services/collaboration/pkg/font/service.go create mode 100644 services/collaboration/pkg/font/service_test.go create mode 100644 services/collaboration/pkg/font/testdata/arimo-regular.png create mode 100644 services/collaboration/pkg/font/testdata/arimo-regular.ttf create mode 100644 services/collaboration/pkg/font/testdata/fontconfiguration.json create mode 100644 services/collaboration/pkg/font/testdata/props.txt diff --git a/.gitignore b/.gitignore index 4444c17049..79d46d1d89 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,10 @@ go.work.sum .DS_Store # example deployments -**/opencloud-sandbox-* \ No newline at end of file +**/opencloud-sandbox-* + +# web apps +!./services/web/assets/ +!./services/web/assets/apps/ +!./services/web/assets/apps/collaboration-settings +!./services/web/assets/apps/collaboration-settings/** diff --git a/services/collaboration/pkg/collaboration/collaboration.go b/services/collaboration/pkg/collaboration/collaboration.go new file mode 100644 index 0000000000..970846be62 --- /dev/null +++ b/services/collaboration/pkg/collaboration/collaboration.go @@ -0,0 +1,39 @@ +package collaboration + +import ( + "context" + "fmt" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + permissionsapi "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" + rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + revactx "github.com/opencloud-eu/reva/v2/pkg/ctx" +) + +type Permission string + +const ( + PermissionCollaborationManageFonts Permission = "Collaboration.Fonts.Manage" +) + +func CheckPermissions(gatewayClient gateway.GatewayAPIClient, ctx context.Context, permission Permission) (*userpb.User, bool, error) { + user, ok := revactx.ContextGetUser(ctx) + if !ok { + return nil, false, fmt.Errorf("could not get user from context") + } + + rsp, err := gatewayClient.CheckPermission(ctx, &permissionsapi.CheckPermissionRequest{ + Permission: string(permission), + SubjectRef: &permissionsapi.SubjectReference{ + Spec: &permissionsapi.SubjectReference_UserId{ + UserId: user.GetId(), + }, + }, + }) + if err != nil { + return user, false, fmt.Errorf("could not check permissions: %w", err) + } + + return user, rsp.GetStatus().GetCode() == rpc.Code_CODE_OK, nil +} diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index afbd1ebf7f..38de01be32 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -4,27 +4,32 @@ import ( "context" "fmt" "net" + "net/url" "os/signal" "time" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/opencloud-eu/reva/v2/pkg/store" + "github.com/spf13/afero" + + "github.com/spf13/cobra" + "go-micro.dev/v4/selector" + microstore "go-micro.dev/v4/store" + "github.com/opencloud-eu/opencloud/pkg/config/configlog" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/registry" "github.com/opencloud-eu/opencloud/pkg/runner" "github.com/opencloud-eu/opencloud/pkg/tracing" + "github.com/opencloud-eu/opencloud/pkg/x/io/fsx" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/config" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/config/parser" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/connector" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/font" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/helpers" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/debug" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/grpc" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/http" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" - "github.com/opencloud-eu/reva/v2/pkg/store" - - "github.com/spf13/cobra" - "go-micro.dev/v4/selector" - microstore "go-micro.dev/v4/store" ) // Server is the entrypoint for the server command. @@ -137,6 +142,35 @@ func Server(cfg *config.Config) *cobra.Command { } gr.Add(runner.NewGolangHttpServerRunner(cfg.Service.Name+".debug", debugServer)) + var fontService font.Service + { + fontFS := afero.NewBasePathFs(fsx.NewOsFs(), cfg.Font.AssetPath) + if err := fontFS.MkdirAll("/", 0o755); err != nil { + logger.Error().Err(err).Msg("Failed to initialize the fonts directory") + return err + } + + fontServiceRootURI, err := url.JoinPath(cfg.Commons.OpenCloudURL, "/collaboration/fonts") + if err := fontFS.MkdirAll("/", 0o755); err != nil { + logger.Error().Err(err).Msg("Failed to build font service root uri") + return err + } + + service, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(fontFS). + WithRootURI(fontServiceRootURI). + WithGatewaySelector(gatewaySelector). + WithLogger(logger). + WithPreviewText(cfg.Font.PreviewText), + ) + if err != nil { + return err + } + + fontService = service + } + // start HTTP server httpServer, err := http.Server( http.Adapter(connector.NewHttpAdapter(gatewaySelector, cfg, st, selector.NewSelector(selector.Registry(registry.GetRegistry())))), @@ -145,6 +179,7 @@ func Server(cfg *config.Config) *cobra.Command { http.Context(ctx), http.TracerProvider(traceProvider), http.Store(st), + http.FontService(fontService), ) if err != nil { logger.Info().Err(err).Str("transport", "http").Msg("Failed to initialize server") diff --git a/services/collaboration/pkg/config/config.go b/services/collaboration/pkg/config/config.go index 9b4594bd93..bee6021ccb 100644 --- a/services/collaboration/pkg/config/config.go +++ b/services/collaboration/pkg/config/config.go @@ -12,6 +12,7 @@ type Config struct { Service Service `yaml:"-"` App App `yaml:"app"` + Font Font `yaml:"font"` Store Store `yaml:"store"` TokenManager *TokenManager `yaml:"token_manager"` diff --git a/services/collaboration/pkg/config/defaults/defaultconfig.go b/services/collaboration/pkg/config/defaults/defaultconfig.go index 20aaf45b86..bc81fd5511 100644 --- a/services/collaboration/pkg/config/defaults/defaultconfig.go +++ b/services/collaboration/pkg/config/defaults/defaultconfig.go @@ -1,8 +1,10 @@ package defaults import ( + "path/filepath" "time" + "github.com/opencloud-eu/opencloud/pkg/config/defaults" "github.com/opencloud-eu/opencloud/pkg/shared" "github.com/opencloud-eu/opencloud/pkg/structs" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/config" @@ -33,6 +35,10 @@ func DefaultConfig() *config.Config { Duration: "12h", }, }, + Font: config.Font{ + AssetPath: filepath.Join(defaults.BaseDataPath(), "collaboration/fonts"), + PreviewText: "OpenCloud", + }, Store: config.Store{ Store: "nats-js-kv", Nodes: []string{"127.0.0.1:9233"}, diff --git a/services/collaboration/pkg/config/font.go b/services/collaboration/pkg/config/font.go new file mode 100644 index 0000000000..5782470788 --- /dev/null +++ b/services/collaboration/pkg/config/font.go @@ -0,0 +1,6 @@ +package config + +type Font struct { + AssetPath string `yaml:"asset_path" env:"COLLABORATION_FONT_ASSET_PATH" desc:"Serve fonts from a path on the filesystem instead of the builtin assets. If not defined, the root directory derives from $OC_BASE_DATA_PATH/collaboration/fonts" introductionVersion:"%%NEXT%%"` + PreviewText string `yaml:"preview_text" env:"COLLABORATION_FONT_PREVIEW_TEXT" desc:"The text that will be displayed in the font preview." introductionVersion:"%%NEXT%%"` +} diff --git a/services/collaboration/pkg/font/service.go b/services/collaboration/pkg/font/service.go new file mode 100644 index 0000000000..d6ed2ca528 --- /dev/null +++ b/services/collaboration/pkg/font/service.go @@ -0,0 +1,350 @@ +package font + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "image" + "image/color" + "image/png" + "io" + "mime" + "net/http" + "net/url" + "path" + "path/filepath" + "strconv" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + "github.com/go-playground/validator/v10" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/pkg/errors" + "github.com/spf13/afero" + "golang.org/x/image/font" + "golang.org/x/image/font/opentype" + "golang.org/x/image/font/sfnt" + "golang.org/x/image/math/fixed" + + "github.com/opencloud-eu/opencloud/pkg/log" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/collaboration" +) + +type ServiceOptions struct { + logger log.Logger `validate:"required"` + fontFS afero.Fs `validate:"required"` + rootURI string `validate:"required,url"` + previewText string `validate:"required,min=1"` + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] `validate:"required"` +} + +func (o ServiceOptions) WithFontFS(fSys afero.Fs) ServiceOptions { + o.fontFS = fSys + return o +} + +func (o ServiceOptions) WithRootURI(rootURI string) ServiceOptions { + o.rootURI = rootURI + return o +} + +func (o ServiceOptions) WithLogger(logger log.Logger) ServiceOptions { + o.logger = logger + return o +} + +func (o ServiceOptions) WithPreviewText(txt string) ServiceOptions { + o.previewText = txt + return o +} + +func (o ServiceOptions) WithGatewaySelector(gws pool.Selectable[gateway.GatewayAPIClient]) ServiceOptions { + o.gatewaySelector = gws + return o +} + +func (o ServiceOptions) validate() error { + return validator.New( + validator.WithPrivateFieldValidation(), + validator.WithRequiredStructEnabled(), + ).Struct(o) +} + +type Service struct { + logger log.Logger + fontFS afero.Fs + rootURI string + previewText string + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] +} + +func NewService(options ServiceOptions) (Service, error) { + if err := options.validate(); err != nil { + return Service{}, err + } + + return Service(options), nil +} + +func (s Service) DeleteFont(w http.ResponseWriter, r *http.Request) { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + _, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationManageFonts) + switch { + case err != nil: + w.WriteHeader(http.StatusInternalServerError) + return + case !canManage: + w.WriteHeader(http.StatusForbidden) + return + } + + fontName := r.PathValue("id") + if fontName == "" { + w.WriteHeader(http.StatusInternalServerError) + return + } + + err = s.fontFS.Remove(fontName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (s Service) GetFont(w http.ResponseWriter, r *http.Request) { + fontName := r.PathValue("id") + if fontName == "" { + w.WriteHeader(http.StatusInternalServerError) + return + } + + b, err := s.getFont(fontName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + contentType := mime.TypeByExtension(filepath.Ext(fontName)) + if contentType == "" { + contentType = "application/octet-stream" + } + + w.Header().Set("Content-Type", contentType) + w.Header().Set("Content-Length", strconv.Itoa(len(b))) + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("X-Content-Type-Options", "nosniff") + + _, _ = w.Write(b) +} + +func (s Service) PreviewFont(w http.ResponseWriter, r *http.Request) { + fontName := r.PathValue("id") + if fontName == "" { + w.WriteHeader(http.StatusInternalServerError) + return + } + + b, err := s.getFont(fontName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + f, err := opentype.Parse(b) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + face, err := opentype.NewFace(f, &opentype.FaceOptions{ + Size: 55, + DPI: 72, + Hinting: font.HintingFull, + }) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + defer func() { + _ = face.Close() + }() + + width := 300 + height := 70 + img := image.NewRGBA(image.Rect(0, 0, width, height)) + + bg := color.RGBA{R: 255, G: 255, B: 255, A: 255} + for i := range img.Pix { + img.Pix[i] = bg.R + } + + d := &font.Drawer{ + Dst: img, + Src: image.NewUniform(color.RGBA{0, 0, 0, 255}), + Face: face, + Dot: fixed.Point26_6{X: fixed.I(10), Y: fixed.I(50)}, + } + + d.DrawString(s.previewText) + + w.Header().Set("Content-Type", "image/png") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + + if err := png.Encode(w, img); err != nil { + http.Error(w, "Failed to encode image", http.StatusInternalServerError) + return + } +} + +func (s Service) ListFonts(w http.ResponseWriter, _ *http.Request) { + fontFiles, err := afero.NewIOFS(s.fontFS).ReadDir(".") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + fontMap := []map[string]any{} + for _, fontFile := range fontFiles { + func() { + uri, err := url.JoinPath(s.rootURI, path.Base(fontFile.Name())) + if err != nil { + return + } + + fontLogger := s.logger.Debug().Str("font", fontFile.Name()) + + b, err := s.getFont(fontFile.Name()) + if err != nil { + fontLogger.Err(err).Msg("could not get font") + return + } + + fnt, err := sfnt.Parse(b) + if err != nil { + fontLogger.Err(err).Msg("could not parse font") + return + } + + buf := new(sfnt.Buffer) + nameID := func(id sfnt.NameID) string { + name, err := fnt.Name(buf, id) + if err != nil { + fontLogger.Err(err).Msg("could not extract font details") + } + + return name + } + + fontMap = append(fontMap, map[string]any{ + "file": path.Base(fontFile.Name()), + "copyright": nameID(sfnt.NameIDCopyright), + "family": nameID(sfnt.NameIDFamily), + "version": nameID(sfnt.NameIDVersion), + "trademark": nameID(sfnt.NameIDTrademark), + "manufacturer": nameID(sfnt.NameIDManufacturer), + "designer": nameID(sfnt.NameIDDesigner), + "description": nameID(sfnt.NameIDDescription), + "vendor_url": nameID(sfnt.NameIDVendorURL), + "designer_url": nameID(sfnt.NameIDDesignerURL), + "license": nameID(sfnt.NameIDLicense), + "license_url": nameID(sfnt.NameIDLicenseURL), + "uri": uri, + // if stamp property changes, the font file will be re-downloaded by collabora + "stamp": fmt.Sprintf("%x", sha256.Sum256(b)), + }) + }() + } + + b, err := json.Marshal(map[string]any{ + "kind": "fontconfiguration", + "server": "OpenCloud Fonts", + "fonts": fontMap, + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + _, err = w.Write(b) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func (s Service) UploadFont(w http.ResponseWriter, r *http.Request) { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + _, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationManageFonts) + switch { + case err != nil: + w.WriteHeader(http.StatusInternalServerError) + return + case !canManage: + w.WriteHeader(http.StatusForbidden) + return + } + + file, fileHeader, err := r.FormFile("font") + switch { + case err != nil && errors.Is(err, http.ErrMissingFile): + w.WriteHeader(http.StatusBadRequest) + return + case err != nil: + w.WriteHeader(http.StatusInternalServerError) + return + } + defer func() { + _ = file.Close() + }() + + b, err := io.ReadAll(file) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + if _, err = sfnt.Parse(b); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + err = afero.WriteFile(s.fontFS, fileHeader.Filename, b, 0o666) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (s Service) getFont(name string) ([]byte, error) { + fontFile, err := s.fontFS.Open(name) + if err != nil { + return nil, fmt.Errorf("could not open font file: %w", err) + } + defer func() { + _ = fontFile.Close() + }() + + fontStat, err := fontFile.Stat() + if err != nil || fontStat.IsDir() { + return nil, fmt.Errorf("could not stat font file: %w", err) + } + + b, err := io.ReadAll(fontFile) + if err != nil || len(b) == 0 { + return nil, fmt.Errorf("could not read font file: %w", err) + } + + return b, nil +} diff --git a/services/collaboration/pkg/font/service_test.go b/services/collaboration/pkg/font/service_test.go new file mode 100644 index 0000000000..102ff0c2c6 --- /dev/null +++ b/services/collaboration/pkg/font/service_test.go @@ -0,0 +1,224 @@ +package font_test + +import ( + "bytes" + "embed" + "io" + "io/fs" + "mime/multipart" + "net/http" + "net/http/httptest" + "testing" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + cs3Permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" + cs3RPC "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + revaCtx "github.com/opencloud-eu/reva/v2/pkg/ctx" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + cs3mocks "github.com/opencloud-eu/reva/v2/tests/cs3mocks/mocks" + "github.com/spf13/afero" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + "google.golang.org/grpc" + + "github.com/opencloud-eu/opencloud/pkg/log" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/font" +) + +//go:embed testdata/* +var testdata embed.FS + +// Helper to create a gatewaySelector +func newGatewaySelector() pool.Selectable[gateway.GatewayAPIClient] { + gatewayAPIClient := &cs3mocks.GatewayAPIClient{} + gatewayAPIClient.On("CheckPermission", mock.Anything, mock.Anything).Return( + &cs3Permissions.CheckPermissionResponse{ + Status: &cs3RPC.Status{ + Code: cs3RPC.Code_CODE_OK, + }, + }, nil) + gatewaySelector := pool.GetSelector[gateway.GatewayAPIClient]( + "GatewaySelector", + "eu.opencloud.api.gateway", + func(cc grpc.ClientConnInterface) gateway.GatewayAPIClient { + return gatewayAPIClient + }, + ) + + return gatewaySelector +} + +func TestService_PreviewFont(t *testing.T) { + testFS := afero.NewMemMapFs() + svc, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(testFS). + WithPreviewText("a"). + WithLogger(log.NopLogger()). + WithRootURI("http://test.local"). + WithGatewaySelector(newGatewaySelector()), + ) + require.NoError(t, err) + + testDataFontB, err := testdata.ReadFile("testdata/arimo-regular.ttf") + require.NoError(t, err) + + testDataFontPNG, err := testdata.ReadFile("testdata/arimo-regular.png") + require.NoError(t, err) + + _ = afero.WriteFile(testFS, "arimo-regular.ttf", testDataFontB, 0644) + defer func() { + require.NoError(t, testFS.Remove("arimo-regular.ttf")) + }() + + req, _ := http.NewRequest(http.MethodGet, "/", nil) + req.SetPathValue("id", "arimo-regular.ttf") + resp := httptest.NewRecorder() + svc.PreviewFont(resp, req) + require.Equal(t, resp.Body.Bytes(), testDataFontPNG) +} + +func TestService_DeleteFont(t *testing.T) { + testFS := afero.NewMemMapFs() + svc, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(testFS). + WithPreviewText("a"). + WithLogger(log.NopLogger()). + WithRootURI("http://test.local"). + WithGatewaySelector(newGatewaySelector()), + ) + require.NoError(t, err) + + testDataFontB, err := testdata.ReadFile("testdata/arimo-regular.ttf") + require.NoError(t, err) + + _ = afero.WriteFile(testFS, "arimo-regular.ttf", testDataFontB, 0644) + + _, err = testFS.Stat("arimo-regular.ttf") // ensure the file exists before deletion + require.NoError(t, err) + + req, _ := http.NewRequest(http.MethodGet, "/", nil) + req.SetPathValue("id", "arimo-regular.ttf") + req = req.WithContext(revaCtx.ContextSetUser(req.Context(), &userpb.User{ + Id: &userpb.UserId{ + OpaqueId: "user", + }, + })) + + resp := httptest.NewRecorder() + svc.DeleteFont(resp, req) + + _, err = testFS.Stat("arimo-regular.ttf") // ensure the file exists before deletion + require.ErrorIs(t, err, fs.ErrNotExist) +} + +func TestService_GetFont(t *testing.T) { + testFS := afero.NewMemMapFs() + svc, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(testFS). + WithPreviewText("a"). + WithLogger(log.NopLogger()). + WithRootURI("http://test.local"). + WithGatewaySelector(newGatewaySelector()), + ) + require.NoError(t, err) + + testDataFontB, err := testdata.ReadFile("testdata/arimo-regular.ttf") + require.NoError(t, err) + + _ = afero.WriteFile(testFS, "arimo-regular.ttf", testDataFontB, 0644) + defer func() { + require.NoError(t, testFS.Remove("arimo-regular.ttf")) + }() + + req, _ := http.NewRequest(http.MethodGet, "/", nil) + req.SetPathValue("id", "arimo-regular.ttf") + resp := httptest.NewRecorder() + svc.GetFont(resp, req) + require.Equal(t, resp.Body.Bytes(), testDataFontB) +} + +func TestService_ListFonts(t *testing.T) { + testFS := afero.NewMemMapFs() + svc, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(testFS). + WithPreviewText("a"). + WithLogger(log.NopLogger()). + WithRootURI("http://test.local"). + WithGatewaySelector(newGatewaySelector()), + ) + require.NoError(t, err) + + t.Run("no fonts", func(t *testing.T) { + req, _ := http.NewRequest(http.MethodGet, "/", nil) + resp := httptest.NewRecorder() + svc.ListFonts(resp, req) + + jsonData := gjson.Parse(resp.Body.String()) + require.Equal(t, jsonData.Get("fonts").String(), "[]") // empty array, not `null` + }) + + t.Run("with fonts", func(t *testing.T) { + testDataFontB, err := testdata.ReadFile("testdata/arimo-regular.ttf") + require.NoError(t, err) + + fontconfigurationB, err := testdata.ReadFile("testdata/fontconfiguration.json") + require.NoError(t, err) + + _ = afero.WriteFile(testFS, "arimo-regular.ttf", testDataFontB, 0644) + defer func() { + require.NoError(t, testFS.Remove("arimo-regular.ttf")) + }() + + req, _ := http.NewRequest(http.MethodGet, "/", nil) + resp := httptest.NewRecorder() + svc.ListFonts(resp, req) + + jsonData := gjson.Parse(resp.Body.String()) + require.JSONEq(t, jsonData.String(), string(fontconfigurationB)) + }) +} + +func TestService_UploadFont(t *testing.T) { + testFS := afero.NewMemMapFs() + svc, err := font.NewService( + font.ServiceOptions{}. + WithFontFS(testFS). + WithPreviewText("a"). + WithLogger(log.NopLogger()). + WithRootURI("http://test.local"). + WithGatewaySelector(newGatewaySelector()), + ) + require.NoError(t, err) + + testDataFontB, err := testdata.ReadFile("testdata/arimo-regular.ttf") + require.NoError(t, err) + + var b bytes.Buffer + w := multipart.NewWriter(&b) + part, _ := w.CreateFormFile("font", "arimo-regular.ttf") + _, _ = part.Write(testDataFontB) + _ = w.Close() + + req, _ := http.NewRequest(http.MethodPost, "/", &b) + req.Header.Set("Content-Type", w.FormDataContentType()) + req = req.WithContext(revaCtx.ContextSetUser(req.Context(), &userpb.User{ + Id: &userpb.UserId{ + OpaqueId: "user", + }, + })) + resp := httptest.NewRecorder() + + svc.UploadFont(resp, req) + testFSFontF, err := testFS.Open("arimo-regular.ttf") + require.NoError(t, err) + + testFSFontB, err := io.ReadAll(testFSFontF) + require.NoError(t, err) + require.Equal(t, testDataFontB, testFSFontB) +} diff --git a/services/collaboration/pkg/font/testdata/arimo-regular.png b/services/collaboration/pkg/font/testdata/arimo-regular.png new file mode 100644 index 0000000000000000000000000000000000000000..9d843850c71b6fe6e5f64db8b112ca8b9837ab50 GIT binary patch literal 1326 zcma)+{WsGK9LK*Kw{|>j!&SFC3pv^CGB;eQW@!yG?$YWk4O5YcsFrIU!aPf@9VA7K z)RKnIR9GH%S+2VzB#lhc<{{77JS@%b{(^h%FQ4;1=X2ig&*z8F=XJ%OV!Z zV;=&Z3;-Z|o%Vu&byd9?`xpT9mwoUDkHz1a9SM#gp9eZGvhSNx))?)~Yvqfsur69Y z4OP)pUP?|!n@-!jn0Xvi(KSUS=9ar$i!t3D5h@NomtH84+!05|^#5_NzRIm~{ZPRj zZQb17eF=kKSB2AilaR?Vtx@x@y~C4|0`&nEqM`-FO38tMP=_*s8`e1B70enqlM7=x z;UOMB+31%W!NLC7|F6A!#J-lo&nMUxN~$*~=;9MM-BZ3dk}8`ntLw;BGEp)ZLdk)D z(`-0~v}WS&vDxeuPS%p){IE6p(l-_fl!@1;0Yl`ds5?j(8 zewSpIPY9>ek5=7~&am+|va^#tW!n*muv@jXbTFjfRZ#30!r1aEtS&7rt={=(cD8h; zh+r#IkG3Z7NJX8D9#%sZb`cz4{|uN)Bb8dNsauU5f;fqpDjbm9R zuG6C;pO@@^J*jk0-p9&#)Bq>)-g2>677+WVJSH-7S3W_(5T0`_?HVWY$St(dZ#8O8 zJf<}@@CVpKl8w=(3~ZSr!o(4cUODLtXtF{w&CJYtxbEv}CB0`wua_B*cXM)LEKd&* zc}uIs<_1~hs$(c~Zw|8PyLAyUR1mPM=!4W)4`O^a)7jaXIWHSJ@@a0kVLK-N!q?B9 z8Ew6BMZ@8s~vRsC#`%CG_gwfr{vj9ODaS)ki}Wp3DVi<(Q<>xJgpy!#R>8&j!N zTwg9Gp}=n^Gbku9P%d-_#&+Z_zN_LK zDU7b27N80xjePEbRN51%mV29287Qh3G8brWh>6-47v)}1(iGq}NZ>RyrfN4T50^C_ zKj%8Ey9o!2t3)0(Ab?QWA0kT8e3g4EF@}W_b55r(ub?kNQJbio=oaTd#~BGc@~IQ` zR~L`~?%>v$>FHhSwtLi?xY*cd!bO?zQuHK7_fEy5L4b+T+da#5_UoE;W`X#ZYRb&u z;H`nkXcJvNJ9H5g*CxNa>{_ZDEF6g`A`Zm0XBlq6AbWayVXF&5OOwtgAtHMVL*~So zI7ho|1!%HY=|@}^%uJxrp6>25Plu>A52Z84n=(31@4fi>C7PetaoXv2*w(+poW=&M sJbdlo;J>i#Ihp?(4F7?Zbw>cuYL#W7)qRqetvU_@KAt3eE$(Fczt3KJ0RR91 literal 0 HcmV?d00001 diff --git a/services/collaboration/pkg/font/testdata/arimo-regular.ttf b/services/collaboration/pkg/font/testdata/arimo-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..22d58b65bdd0f5d24b1111fb15cf1dffc9341b7e GIT binary patch literal 315784 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 literal 0 HcmV?d00001 diff --git a/services/collaboration/pkg/font/testdata/fontconfiguration.json b/services/collaboration/pkg/font/testdata/fontconfiguration.json new file mode 100644 index 0000000000..e429a646aa --- /dev/null +++ b/services/collaboration/pkg/font/testdata/fontconfiguration.json @@ -0,0 +1,22 @@ +{ + "fonts": [ + { + "copyright": "Copyright 2020 The Arimo Project Authors (https://github.com/googlefonts/arimo)", + "description": "Arimo was designed by Steve Matteson as an innovative, refreshing sans serif design that is metrically compatible with Arial(tm). Arimo offers improved on-screen readability characteristics and the pan-European WGL character set and solves the needs of developers looking for width-compatible fonts to address document portability across platforms.", + "designer": "Steve Matteson", + "designer_url": "http://www.monotype.com/studio", + "family": "Arimo", + "file": "arimo-regular.ttf", + "license": "This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.", + "license_url": "http://scripts.sil.org/OFL", + "manufacturer": "Monotype Imaging Inc.", + "stamp": "f405056d25ddc3ad89a852db367f1dc075d8c7212fddcf7c488e212efeb8b176", + "trademark": "Arimo is a trademark of Google Inc.", + "uri": "http://test.local/arimo-regular.ttf", + "vendor_url": "http://www.google.com/get/noto/", + "version": "Version 1.33" + } + ], + "kind": "fontconfiguration", + "server": "OpenCloud Fonts" +} diff --git a/services/collaboration/pkg/font/testdata/props.txt b/services/collaboration/pkg/font/testdata/props.txt new file mode 100644 index 0000000000..0fbf3453dc --- /dev/null +++ b/services/collaboration/pkg/font/testdata/props.txt @@ -0,0 +1 @@ +arimo-regular.ttf: https://github.com/ryanoasis/nerd-fonts/blob/master/src/unpatched-fonts/Arimo/Regular/Arimo-Regular.ttf diff --git a/services/collaboration/pkg/server/http/option.go b/services/collaboration/pkg/server/http/option.go index ce7dd58ebc..7d13bd7d61 100644 --- a/services/collaboration/pkg/server/http/option.go +++ b/services/collaboration/pkg/server/http/option.go @@ -3,17 +3,19 @@ package http import ( "context" + microstore "go-micro.dev/v4/store" + "go.opentelemetry.io/otel/trace" + "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/config" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/connector" - microstore "go-micro.dev/v4/store" - "go.opentelemetry.io/otel/trace" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/font" ) // Option defines a single option function. type Option func(o *Options) -// Options defines the available options for this package. +// Options define the available options for this package. type Options struct { Adapter *connector.HttpAdapter Logger log.Logger @@ -21,6 +23,7 @@ type Options struct { Config *config.Config TracerProvider trace.TracerProvider Store microstore.Store + FontService font.Service } // newOptions initializes the available default options. @@ -34,7 +37,7 @@ func newOptions(opts ...Option) Options { return opt } -// App provides a function to set the logger option. +// Adapter provides a function to set the Adapter option. func Adapter(val *connector.HttpAdapter) Option { return func(o *Options) { o.Adapter = val @@ -75,3 +78,10 @@ func Store(val microstore.Store) Option { o.Store = val } } + +// FontService provides a function to set the FontService option +func FontService(val font.Service) Option { + return func(o *Options) { + o.FontService = val + } +} diff --git a/services/collaboration/pkg/server/http/server.go b/services/collaboration/pkg/server/http/server.go index bd8953532e..8a315823f5 100644 --- a/services/collaboration/pkg/server/http/server.go +++ b/services/collaboration/pkg/server/http/server.go @@ -6,6 +6,9 @@ import ( "github.com/go-chi/chi/v5" chimiddleware "github.com/go-chi/chi/v5/middleware" + "github.com/riandyrn/otelchi" + "go-micro.dev/v4" + "github.com/opencloud-eu/opencloud/pkg/account" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/middleware" @@ -13,8 +16,6 @@ import ( "github.com/opencloud-eu/opencloud/pkg/tracing" "github.com/opencloud-eu/opencloud/pkg/version" colabmiddleware "github.com/opencloud-eu/opencloud/services/collaboration/pkg/middleware" - "github.com/riandyrn/otelchi" - "go-micro.dev/v4" ) // Server initializes the http service and server. @@ -94,6 +95,7 @@ func Server(opts ...Option) (http.Service, error) { // prepareRoutes will prepare all the implemented routes func prepareRoutes(r *chi.Mux, options Options) { + fontService := options.FontService adapter := options.Adapter logger := options.Logger // prepare basic logger for the request @@ -209,5 +211,21 @@ func prepareRoutes(r *chi.Mux, options Options) { adapter.GetAvatar(w, r) }) }) + + }) + r.Route("/collaboration", func(r chi.Router) { + r.Route("/fonts", func(r chi.Router) { + r.Get("/", fontService.ListFonts) + r.Get("/{id}", fontService.GetFont) + r.Get("/preview/{id}", fontService.PreviewFont) + r.Route("/manage", func(r chi.Router) { + r.Use(middleware.ExtractAccountUUID( + account.Logger(options.Logger), + account.JWTSecret(options.Config.TokenManager.JWTSecret), + )) + r.Post("/", fontService.UploadFont) + r.Delete("/{id}", fontService.DeleteFont) + }) + }) }) } diff --git a/services/proxy/pkg/config/defaults/defaultconfig.go b/services/proxy/pkg/config/defaults/defaultconfig.go index 187e52be6f..5dd3541e18 100644 --- a/services/proxy/pkg/config/defaults/defaultconfig.go +++ b/services/proxy/pkg/config/defaults/defaultconfig.go @@ -291,6 +291,16 @@ func DefaultPolicies() []config.Policy { Unprotected: true, SkipXAccessToken: true, }, + { + Endpoint: "/collaboration/fonts/manage/", + Service: "eu.opencloud.web.collaboration", + // Method: "POST" // toDo: fails with method, WHY??? + }, + { + Endpoint: "/collaboration", + Service: "eu.opencloud.web.collaboration", + Unprotected: true, + }, }, }, } diff --git a/services/proxy/pkg/middleware/authentication.go b/services/proxy/pkg/middleware/authentication.go index 7703fdf62b..4c7b879699 100644 --- a/services/proxy/pkg/middleware/authentication.go +++ b/services/proxy/pkg/middleware/authentication.go @@ -7,12 +7,13 @@ import ( "regexp" "strings" - "github.com/opencloud-eu/opencloud/services/proxy/pkg/router" - "github.com/opencloud-eu/opencloud/services/proxy/pkg/webdav" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "golang.org/x/text/cases" "golang.org/x/text/language" + + "github.com/opencloud-eu/opencloud/services/proxy/pkg/router" + "github.com/opencloud-eu/opencloud/services/proxy/pkg/webdav" ) var ( diff --git a/services/settings/pkg/store/defaults/defaults.go b/services/settings/pkg/store/defaults/defaults.go index cc7a9bacee..c65a3548c1 100644 --- a/services/settings/pkg/store/defaults/defaults.go +++ b/services/settings/pkg/store/defaults/defaults.go @@ -79,6 +79,7 @@ func ServiceAccountBundle() *settingsmsg.Bundle { Settings: []*settingsmsg.Setting{ AccountManagementPermission(All), ChangeLogoPermission(All), + CollaborationManageFontsPermission(All), CreatePublicLinkPermission(All), CreateSharePermission(All), CreateSpacesPermission(All), @@ -115,6 +116,7 @@ func generateBundleAdminRole() *settingsmsg.Bundle { AccountManagementPermission(All), AutoAcceptSharesPermission(Own), ChangeLogoPermission(All), + CollaborationManageFontsPermission(All), CreatePublicLinkPermission(All), CreateSharePermission(All), CreateSpacesPermission(All), diff --git a/services/settings/pkg/store/defaults/permissions.go b/services/settings/pkg/store/defaults/permissions.go index fb661fd20d..dec6aed3f0 100644 --- a/services/settings/pkg/store/defaults/permissions.go +++ b/services/settings/pkg/store/defaults/permissions.go @@ -67,6 +67,25 @@ func ChangeLogoPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Sett } } +// ManageFontsPermission is the permission to manage fonts +func CollaborationManageFontsPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { + return &settingsmsg.Setting{ + Id: "ed83fc10-1f54-4a9e-b5a7-fb517f5f3e01", + Name: "Collaboration.Fonts.Manage", + DisplayName: "Manage fonts", + Description: "This permission permits to manage the collaboration fonts.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: c, + }, + }, + } +} + // CreatePublicLinkPermission is the permission to create public links func CreatePublicLinkPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { return &settingsmsg.Setting{ diff --git a/services/web/Makefile b/services/web/Makefile index 7835ac6bbe..453122a865 100644 --- a/services/web/Makefile +++ b/services/web/Makefile @@ -13,11 +13,10 @@ include ../../.make/release.mk include ../../.make/docs.mk .PHONY: node-generate-dev -node-generate-dev: pull-assets +node-generate-dev: pull-assets build-apps .PHONY: node-generate-prod -node-generate-prod: download-assets - +node-generate-prod: download-assets build-apps .PHONY: pull-assets pull-assets: @@ -43,6 +42,13 @@ download-assets: git clean -xfd assets curl --fail -slL -o- https://github.com/opencloud-eu/web/releases/download/$(WEB_ASSETS_VERSION)/web.tar.gz | tar xzf - -C assets/core/ +.PHONY: build-apps +build-apps: + @for dir in ./assets/apps/*; do \ + echo "📦 Installing in $$dir"; \ + (cd "$$dir" && pnpm install && pnpm build) || exit 1; \ + done + .PHONY: ci-node-save-licenses ci-node-save-licenses: @mkdir -p ../../third-party-licenses/node/web diff --git a/services/web/pkg/apps/apps.go b/services/web/pkg/apps/apps.go index 9e7f8c90c5..1a6b3bbb84 100644 --- a/services/web/pkg/apps/apps.go +++ b/services/web/pkg/apps/apps.go @@ -89,20 +89,28 @@ func List(logger log.Logger, data map[string]config.App, fSystems ...fs.FS) []Ap appData = data } - application, err := build(fSystem, name, appData) - if err != nil { - // if app creation fails, log the error and continue with the next app - logger.Debug().Err(err).Str("path", entry.Name()).Msg("failed to load application") - continue - } + for _, appRoot := range []string{ + name, + path.Join(name, "dist"), // some applications have their artifacts in the dist/ folder + } { + application, err := build(fSystem, appRoot, appData) + if err != nil { + // if app creation fails, log the error and continue with the next app + logger.Debug().Err(err).Str("path", entry.Name()).Msg("failed to load application") + continue + } - if application.Disabled { - // if the app is disabled, skip it - continue - } + if application.Disabled { + // if the app is disabled, skip it + continue + } - // everything is fine, add the application to the list of applications - registry[name] = application + // everything is fine, add the application to the list of applications + registry[name] = application + + // application found, done here + break + } } } @@ -123,7 +131,9 @@ func build(fSystem fs.FS, id string, globalConfig config.App) (Application, erro if err != nil { return Application{}, errors.Join(err, ErrMissingManifest) } - defer r.Close() + defer func() { + _ = r.Close() + }() if json.NewDecoder(r).Decode(&application) != nil { return Application{}, errors.Join(err, ErrInvalidManifest) diff --git a/services/web/pkg/apps/apps_test.go b/services/web/pkg/apps/apps_test.go index f36c3df676..963794e532 100644 --- a/services/web/pkg/apps/apps_test.go +++ b/services/web/pkg/apps/apps_test.go @@ -181,8 +181,20 @@ func TestList(t *testing.T) { "app-3/manifest.json": &fstest.MapFile{ Data: []byte(`{"id":"app-3", "entrypoint":"entrypoint.js", "config": {"foo": "fs2"}}`), }, + }, fstest.MapFS{ + "app-unknown": dir, + "app-unknown/bin/entrypoint.js": &fstest.MapFile{}, + "app-unknown/bin/manifest.json": &fstest.MapFile{ + Data: []byte(`{"id":"app-unknown", "entrypoint":"entrypoint.js"}`), + }, + }, fstest.MapFS{ + "app-dist": dir, + "app-dist/dist/entrypoint.js": &fstest.MapFile{}, + "app-dist/dist/manifest.json": &fstest.MapFile{ + Data: []byte(`{"id":"app-dist", "entrypoint":"entrypoint.js", "config": {"folder": "dist"}}`), + }, }) - g.Expect(len(applications)).To(gomega.Equal(3)) + g.Expect(len(applications)).To(gomega.Equal(4)) for _, application := range applications { switch { @@ -193,6 +205,8 @@ func TestList(t *testing.T) { case application.Entrypoint == "app-3/entrypoint.js": g.Expect(application.Config["foo"]).To(gomega.Equal("local conf 1")) g.Expect(application.Config["bar"]).To(gomega.Equal("local conf 2")) + case application.Entrypoint == "app-dist/dist/entrypoint.js": + g.Expect(application.Config["folder"]).To(gomega.Equal("dist")) default: t.Fatalf("unexpected application %s", application.Entrypoint) } diff --git a/services/web/pkg/service/v0/service.go b/services/web/pkg/service/v0/service.go index a16ba5336f..e21e9bc637 100644 --- a/services/web/pkg/service/v0/service.go +++ b/services/web/pkg/service/v0/service.go @@ -19,7 +19,6 @@ import ( "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/middleware" "github.com/opencloud-eu/opencloud/pkg/tracing" - "github.com/opencloud-eu/opencloud/pkg/x/io/fsx" "github.com/opencloud-eu/opencloud/services/web/pkg/assets" "github.com/opencloud-eu/opencloud/services/web/pkg/config" "github.com/opencloud-eu/opencloud/services/web/pkg/theme" @@ -54,8 +53,6 @@ func NewService(opts ...Option) (Service, error) { logger: options.Logger, config: options.Config, mux: m, - coreFS: options.CoreFS, - themeFS: options.ThemeFS, gatewaySelector: options.GatewaySelector, } @@ -92,7 +89,7 @@ func NewService(opts ...Option) (Service, error) { options.Config.HTTP.CacheTTL, )) r.Mount("/", svc.Static( - svc.coreFS, + options.CoreFS, svc.config.HTTP.Root, options.Config.HTTP.CacheTTL, )) @@ -110,8 +107,6 @@ type Web struct { logger log.Logger config *config.Config mux *chi.Mux - coreFS fs.FS - themeFS *fsx.FallbackFS gatewaySelector pool.Selectable[gateway.GatewayAPIClient] } From f1208cfa329e6728529fa97c7037eb52292143b8 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Tue, 9 Jun 2026 17:15:23 +0200 Subject: [PATCH 2/6] enhancement: make collaboration mention functionality public --- .woodpecker.star | 1 + pkg/events/events.go | 22 +++ .../pkg/collaboration/collaboration.go | 3 +- services/collaboration/pkg/command/server.go | 22 +++ services/collaboration/pkg/config/config.go | 3 + .../pkg/config/defaults/defaultconfig.go | 8 + services/collaboration/pkg/config/event.go | 12 ++ .../pkg/notification/notification.go | 10 ++ .../collaboration/pkg/notification/service.go | 152 ++++++++++++++++++ .../collaboration/pkg/server/http/option.go | 23 ++- .../collaboration/pkg/server/http/server.go | 14 +- services/notifications/pkg/command/server.go | 12 +- services/notifications/pkg/email/composer.go | 10 +- services/notifications/pkg/email/templates.go | 13 ++ .../notifications/pkg/service/resource.go | 99 ++++++++++++ services/notifications/pkg/service/service.go | 20 ++- .../pkg/config/defaults/defaultconfig.go | 7 +- services/settings/pkg/service/v0/service.go | 12 +- .../pkg/service/v0/servicedecorator.go | 1 + .../settings/pkg/store/defaults/defaults.go | 23 +++ .../pkg/store/defaults/permissions.go | 21 ++- .../settings/pkg/store/defaults/templates.go | 4 + services/userlog/pkg/command/server.go | 4 + services/userlog/pkg/service/conversion.go | 43 ++++- services/userlog/pkg/service/filter.go | 8 +- services/userlog/pkg/service/service.go | 6 + services/userlog/pkg/service/templates.go | 5 + 27 files changed, 521 insertions(+), 37 deletions(-) create mode 100644 pkg/events/events.go create mode 100644 services/collaboration/pkg/config/event.go create mode 100644 services/collaboration/pkg/notification/notification.go create mode 100644 services/collaboration/pkg/notification/service.go create mode 100644 services/notifications/pkg/service/resource.go diff --git a/.woodpecker.star b/.woodpecker.star index a7225d986b..be3f297434 100644 --- a/.woodpecker.star +++ b/.woodpecker.star @@ -3215,6 +3215,7 @@ def wopiCollaborationService(name): "COLLABORATION_CS3API_DATAGATEWAY_INSECURE": True, "OC_JWT_SECRET": "some-opencloud-jwt-secret", "COLLABORATION_WOPI_SECRET": "some-wopi-secret", + "COLLABORATION_EVENTS_ENDPOINT": "%s:9233" % OC_SERVER_NAME, } if name == "collabora": diff --git a/pkg/events/events.go b/pkg/events/events.go new file mode 100644 index 0000000000..3af491210f --- /dev/null +++ b/pkg/events/events.go @@ -0,0 +1,22 @@ +package events + +import ( + "encoding/json" + "time" + + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +type ResourceMention struct { + Executant *user.UserId + UserIDs []*user.UserId + Ref *provider.Reference + Timestamp time.Time +} + +func (ResourceMention) Unmarshal(v []byte) (interface{}, error) { + e := ResourceMention{} + err := json.Unmarshal(v, &e) + return e, err +} diff --git a/services/collaboration/pkg/collaboration/collaboration.go b/services/collaboration/pkg/collaboration/collaboration.go index 970846be62..13bc628ae0 100644 --- a/services/collaboration/pkg/collaboration/collaboration.go +++ b/services/collaboration/pkg/collaboration/collaboration.go @@ -14,7 +14,8 @@ import ( type Permission string const ( - PermissionCollaborationManageFonts Permission = "Collaboration.Fonts.Manage" + PermissionCollaborationManageFonts Permission = "Collaboration.Fonts.Manage" + PermissionCollaborationPublishNotification Permission = "Collaboration.Notification.Publish" ) func CheckPermissions(gatewayClient gateway.GatewayAPIClient, ctx context.Context, permission Permission) (*userpb.User, bool, error) { diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index 38de01be32..f028e36ded 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -8,6 +8,7 @@ import ( "os/signal" "time" + "github.com/opencloud-eu/reva/v2/pkg/events/stream" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" "github.com/opencloud-eu/reva/v2/pkg/store" "github.com/spf13/afero" @@ -17,6 +18,7 @@ import ( microstore "go-micro.dev/v4/store" "github.com/opencloud-eu/opencloud/pkg/config/configlog" + "github.com/opencloud-eu/opencloud/pkg/generators" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/registry" "github.com/opencloud-eu/opencloud/pkg/runner" @@ -27,6 +29,7 @@ import ( "github.com/opencloud-eu/opencloud/services/collaboration/pkg/connector" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/font" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/helpers" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/notification" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/debug" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/grpc" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/server/http" @@ -171,6 +174,24 @@ func Server(cfg *config.Config) *cobra.Command { fontService = service } + var notificationService notification.Service + { + connName := generators.GenerateConnectionName(cfg.Service.Name, generators.NTypeBus) + natsStream, err := stream.NatsFromConfig(connName, true, stream.NatsConfig(cfg.Events)) + if err != nil { + return err + } + service, err := notification.NewService( + notification.ServiceOptions{}. + WithLogger(logger). + WithGatewaySelector(gatewaySelector). + WithEventPublisher(natsStream). + WithMachineAuthAPIKey(cfg.MachineAuthAPIKey), + ) + + notificationService = service + } + // start HTTP server httpServer, err := http.Server( http.Adapter(connector.NewHttpAdapter(gatewaySelector, cfg, st, selector.NewSelector(selector.Registry(registry.GetRegistry())))), @@ -180,6 +201,7 @@ func Server(cfg *config.Config) *cobra.Command { http.TracerProvider(traceProvider), http.Store(st), http.FontService(fontService), + http.NotificationService(notificationService), ) if err != nil { logger.Info().Err(err).Str("transport", "http").Msg("Failed to initialize server") diff --git a/services/collaboration/pkg/config/config.go b/services/collaboration/pkg/config/config.go index bee6021ccb..c71bebdb48 100644 --- a/services/collaboration/pkg/config/config.go +++ b/services/collaboration/pkg/config/config.go @@ -14,6 +14,7 @@ type Config struct { App App `yaml:"app"` Font Font `yaml:"font"` Store Store `yaml:"store"` + Events Events `yaml:"events"` TokenManager *TokenManager `yaml:"token_manager"` @@ -27,4 +28,6 @@ type Config struct { Debug Debug `yaml:"debug"` Context context.Context `yaml:"-"` + + MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY;COLLABORATION_MACHINE_AUTH_API_KEY" desc:"The machine auth API key used to validate internal requests necessary to access resources from other services." introductionVersion:"%%NEXT%%"` } diff --git a/services/collaboration/pkg/config/defaults/defaultconfig.go b/services/collaboration/pkg/config/defaults/defaultconfig.go index bc81fd5511..df4ea57679 100644 --- a/services/collaboration/pkg/config/defaults/defaultconfig.go +++ b/services/collaboration/pkg/config/defaults/defaultconfig.go @@ -39,6 +39,10 @@ func DefaultConfig() *config.Config { AssetPath: filepath.Join(defaults.BaseDataPath(), "collaboration/fonts"), PreviewText: "OpenCloud", }, + Events: config.Events{ + Endpoint: "127.0.0.1:9233", + Cluster: "opencloud-cluster", + }, Store: config.Store{ Store: "nats-js-kv", Nodes: []string{"127.0.0.1:9233"}, @@ -92,6 +96,10 @@ func EnsureDefaults(cfg *config.Config) { if cfg.CS3Api.GRPCClientTLS == nil && cfg.Commons != nil { cfg.CS3Api.GRPCClientTLS = structs.CopyOrZeroValue(cfg.Commons.GRPCClientTLS) } + + if cfg.MachineAuthAPIKey == "" && cfg.Commons != nil && cfg.Commons.MachineAuthAPIKey != "" { + cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey + } } // Sanitize sanitized the configuration diff --git a/services/collaboration/pkg/config/event.go b/services/collaboration/pkg/config/event.go new file mode 100644 index 0000000000..eccc8b7422 --- /dev/null +++ b/services/collaboration/pkg/config/event.go @@ -0,0 +1,12 @@ +package config + +// Events combines the configuration options for the event bus. +type Events struct { + Endpoint string `yaml:"endpoint" env:"OC_EVENTS_ENDPOINT;COLLABORATION_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture." introductionVersion:"%%NEXT%%"` + Cluster string `yaml:"cluster" env:"OC_EVENTS_CLUSTER;COLLABORATION_EVENTS_CLUSTER" desc:"The clusterID of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture. Mandatory when using NATS as event system." introductionVersion:"%%NEXT%%"` + TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_EVENTS_TLS_INSECURE;COLLABORATION_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"%%NEXT%%"` + TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_EVENTS_TLS_ROOT_CA_CERTIFICATE;COLLABORATION_EVENTS_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided COLLABORATION_EVENTS_TLS_INSECURE will be seen as false." introductionVersion:"%%NEXT%%"` + EnableTLS bool `yaml:"enable_tls" env:"OC_EVENTS_ENABLE_TLS;COLLABORATION_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"%%NEXT%%"` + AuthUsername string `yaml:"username" env:"OC_EVENTS_AUTH_USERNAME;COLLABORATION_EVENTS_AUTH_USERNAME" desc:"The username to authenticate with the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"%%NEXT%%"` + AuthPassword string `yaml:"password" env:"OC_EVENTS_AUTH_PASSWORD;COLLABORATION_EVENTS_AUTH_PASSWORD" desc:"The password to authenticate with the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"%%NEXT%%"` +} diff --git a/services/collaboration/pkg/notification/notification.go b/services/collaboration/pkg/notification/notification.go new file mode 100644 index 0000000000..3b446b5b08 --- /dev/null +++ b/services/collaboration/pkg/notification/notification.go @@ -0,0 +1,10 @@ +package notification + +import ( + "github.com/go-playground/validator/v10" +) + +var validate = validator.New( + validator.WithPrivateFieldValidation(), + validator.WithRequiredStructEnabled(), +) diff --git a/services/collaboration/pkg/notification/service.go b/services/collaboration/pkg/notification/service.go new file mode 100644 index 0000000000..97eff22e95 --- /dev/null +++ b/services/collaboration/pkg/notification/service.go @@ -0,0 +1,152 @@ +package notification + +import ( + "context" + "encoding/json" + "io" + "net/http" + "time" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + revactx "github.com/opencloud-eu/reva/v2/pkg/ctx" + "github.com/opencloud-eu/reva/v2/pkg/events" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/opencloud-eu/reva/v2/pkg/storagespace" + "google.golang.org/grpc/metadata" + + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" + "github.com/opencloud-eu/opencloud/pkg/log" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/collaboration" +) + +type ServiceOptions struct { + logger log.Logger `validate:"required"` + eventPublisher events.Publisher `validate:"required"` + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] `validate:"required"` + machineAuthAPIKey string `validate:"required,min=1"` +} + +func (o ServiceOptions) WithLogger(logger log.Logger) ServiceOptions { + o.logger = logger + return o +} + +func (o ServiceOptions) WithEventPublisher(eventPublisher events.Publisher) ServiceOptions { + o.eventPublisher = eventPublisher + return o +} + +func (o ServiceOptions) WithMachineAuthAPIKey(key string) ServiceOptions { + o.machineAuthAPIKey = key + return o +} + +func (o ServiceOptions) WithGatewaySelector(gws pool.Selectable[gateway.GatewayAPIClient]) ServiceOptions { + o.gatewaySelector = gws + return o +} + +type Service struct { + log log.Logger + eventPublisher events.Publisher + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] + machineAuthAPIKey string +} + +func NewService(options ServiceOptions) (Service, error) { + if err := validate.Struct(options); err != nil { + return Service{}, err + } + + return Service{ + log: options.logger, + eventPublisher: options.eventPublisher, + gatewaySelector: options.gatewaySelector, + machineAuthAPIKey: options.machineAuthAPIKey, + }, nil +} + +func (s Service) HandleNotification(w http.ResponseWriter, r *http.Request) { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + requestUser, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationPublishNotification) + switch { + case err != nil: + w.WriteHeader(http.StatusInternalServerError) + return + case !canManage: + w.WriteHeader(http.StatusForbidden) + return + } + + defer func() { _ = r.Body.Close() }() + body, err := io.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + var data = struct { + Type string `json:"type" validate:"required"` + UserIDs []string `json:"userIDs" validate:"required"` + FileID string `json:"fileID" validate:"required"` + }{} + if err := json.Unmarshal(body, &data); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + if err := validate.Struct(data); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + event := ocEvents.ResourceMention{ + Executant: requestUser.GetId(), + Timestamp: time.Now(), + } + + for _, userID := range data.UserIDs { + authResponse, err := gatewayClient.Authenticate(context.Background(), &gateway.AuthenticateRequest{ + Type: "machine", + ClientId: "userid:" + userID, + ClientSecret: s.machineAuthAPIKey, + }) + if err != nil || authResponse.Status.Code != rpcv1beta1.Code_CODE_OK { + w.WriteHeader(http.StatusInternalServerError) + return + } + + resourceID, err := storagespace.ParseID(data.FileID) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + statResponse, err := gatewayClient.Stat( + metadata.AppendToOutgoingContext(context.Background(), revactx.TokenHeader, authResponse.GetToken()), + &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &resourceID}}, + ) + if err != nil || statResponse.Status.Code != rpcv1beta1.Code_CODE_OK { + w.WriteHeader(http.StatusInternalServerError) + return + } + + event.UserIDs = append(event.UserIDs, authResponse.User.GetId()) + event.Ref = &storageprovider.Reference{ + ResourceId: statResponse.GetInfo().GetId(), + } + } + + if err := events.Publish(r.Context(), s.eventPublisher, event); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} diff --git a/services/collaboration/pkg/server/http/option.go b/services/collaboration/pkg/server/http/option.go index 7d13bd7d61..de009249b4 100644 --- a/services/collaboration/pkg/server/http/option.go +++ b/services/collaboration/pkg/server/http/option.go @@ -10,6 +10,7 @@ import ( "github.com/opencloud-eu/opencloud/services/collaboration/pkg/config" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/connector" "github.com/opencloud-eu/opencloud/services/collaboration/pkg/font" + "github.com/opencloud-eu/opencloud/services/collaboration/pkg/notification" ) // Option defines a single option function. @@ -17,13 +18,14 @@ type Option func(o *Options) // Options define the available options for this package. type Options struct { - Adapter *connector.HttpAdapter - Logger log.Logger - Context context.Context - Config *config.Config - TracerProvider trace.TracerProvider - Store microstore.Store - FontService font.Service + Adapter *connector.HttpAdapter + Logger log.Logger + Context context.Context + Config *config.Config + TracerProvider trace.TracerProvider + Store microstore.Store + FontService font.Service + NotificationService notification.Service } // newOptions initializes the available default options. @@ -85,3 +87,10 @@ func FontService(val font.Service) Option { o.FontService = val } } + +// NotificationService provides a function to set the NotificationService option +func NotificationService(val notification.Service) Option { + return func(o *Options) { + o.NotificationService = val + } +} diff --git a/services/collaboration/pkg/server/http/server.go b/services/collaboration/pkg/server/http/server.go index 8a315823f5..a2f4282c35 100644 --- a/services/collaboration/pkg/server/http/server.go +++ b/services/collaboration/pkg/server/http/server.go @@ -96,6 +96,7 @@ func Server(opts ...Option) (http.Service, error) { // prepareRoutes will prepare all the implemented routes func prepareRoutes(r *chi.Mux, options Options) { fontService := options.FontService + notificationService := options.NotificationService adapter := options.Adapter logger := options.Logger // prepare basic logger for the request @@ -214,15 +215,18 @@ func prepareRoutes(r *chi.Mux, options Options) { }) r.Route("/collaboration", func(r chi.Router) { + auth := middleware.ExtractAccountUUID( + account.Logger(options.Logger), + account.JWTSecret(options.Config.TokenManager.JWTSecret), + ) + r.With(auth).Route("/notify", func(r chi.Router) { + r.Post("/", notificationService.HandleNotification) + }) r.Route("/fonts", func(r chi.Router) { r.Get("/", fontService.ListFonts) r.Get("/{id}", fontService.GetFont) r.Get("/preview/{id}", fontService.PreviewFont) - r.Route("/manage", func(r chi.Router) { - r.Use(middleware.ExtractAccountUUID( - account.Logger(options.Logger), - account.JWTSecret(options.Config.TokenManager.JWTSecret), - )) + r.With(auth).Route("/manage", func(r chi.Router) { r.Post("/", fontService.UploadFont) r.Delete("/{id}", fontService.DeleteFont) }) diff --git a/services/notifications/pkg/command/server.go b/services/notifications/pkg/command/server.go index e512286a6a..0ca677be77 100644 --- a/services/notifications/pkg/command/server.go +++ b/services/notifications/pkg/command/server.go @@ -6,7 +6,12 @@ import ( "os/signal" "reflect" + "github.com/opencloud-eu/reva/v2/pkg/events" + "github.com/opencloud-eu/reva/v2/pkg/events/stream" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/opencloud-eu/opencloud/pkg/config/configlog" + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" "github.com/opencloud-eu/opencloud/pkg/generators" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/registry" @@ -19,14 +24,12 @@ import ( "github.com/opencloud-eu/opencloud/services/notifications/pkg/config/parser" "github.com/opencloud-eu/opencloud/services/notifications/pkg/server/debug" "github.com/opencloud-eu/opencloud/services/notifications/pkg/service" - "github.com/opencloud-eu/reva/v2/pkg/events" - "github.com/opencloud-eu/reva/v2/pkg/events/stream" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" - ehsvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/eventhistory/v0" "github.com/opencloud-eu/reva/v2/pkg/store" "github.com/spf13/cobra" microstore "go-micro.dev/v4/store" + + ehsvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/eventhistory/v0" ) // Server is the entrypoint for the server command. @@ -86,6 +89,7 @@ func Server(cfg *config.Config) *cobra.Command { events.SpaceMembershipExpired{}, events.ScienceMeshInviteTokenGenerated{}, events.SendEmailsEvent{}, + ocEvents.ResourceMention{}, } registeredEvents := make(map[string]events.Unmarshaller) for _, e := range evs { diff --git a/services/notifications/pkg/email/composer.go b/services/notifications/pkg/email/composer.go index 1f81d87f0b..7af545b31c 100644 --- a/services/notifications/pkg/email/composer.go +++ b/services/notifications/pkg/email/composer.go @@ -3,6 +3,7 @@ package email import ( "bytes" "embed" + "fmt" "strings" "text/template" @@ -150,6 +151,11 @@ func callToActionToHTML(s string) string { if strings.TrimSpace(s) == "" { return "" } - s = strings.TrimSuffix(s, "{ShareLink}") - return s + `{ShareLink}` + + // substitute links + for _, token := range []string{"ShareLink", "ResourceLink"} { + s = strings.ReplaceAll(s, "{"+token+"}", fmt.Sprintf(`{%s}`, token, token)) + } + + return s } diff --git a/services/notifications/pkg/email/templates.go b/services/notifications/pkg/email/templates.go index 83eff3da21..99091b44b1 100644 --- a/services/notifications/pkg/email/templates.go +++ b/services/notifications/pkg/email/templates.go @@ -118,6 +118,15 @@ Please visit your federation settings and use the following details: Greeting: l10n.Template(`Hi {DisplayName},`), MessageBody: "", // is generated using the GroupedTemplates } + + Mention = MessageTemplate{ + textTemplate: _textTemplate, + htmlTemplate: _htmlTemplate, + Subject: l10n.Template(`You were mentioned in '{ResourceName}'`), + Greeting: l10n.Template(`Hello {RecipientName},`), + MessageBody: l10n.Template(`{AuthorName} mentioned you in "{ResourceName}".`), + CallToAction: l10n.Template(`You can view the mention here: {ResourceLink}`), + } ) // holds the information to turn the raw template into a parseable go template @@ -134,6 +143,10 @@ var _placeholders = map[string]string{ "{ProviderDomain}": "{{ .ProviderDomain }}", "{Token}": "{{ .Token }}", "{DisplayName}": "{{ .DisplayName }}", + "{AuthorName}": "{{ .AuthorName }}", + "{RecipientName}": "{{ .RecipientName }}", + "{ResourceName}": "{{ .ResourceName }}", + "{ResourceLink}": "{{ .ResourceLink }}", } // MessageTemplate is the data structure for the email diff --git a/services/notifications/pkg/service/resource.go b/services/notifications/pkg/service/resource.go new file mode 100644 index 0000000000..3138f51ebc --- /dev/null +++ b/services/notifications/pkg/service/resource.go @@ -0,0 +1,99 @@ +package service + +import ( + "context" + + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + "github.com/opencloud-eu/reva/v2/pkg/storagespace" + "github.com/opencloud-eu/reva/v2/pkg/utils" + + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" + "github.com/opencloud-eu/opencloud/pkg/l10n" + "github.com/opencloud-eu/opencloud/services/notifications/pkg/channels" + "github.com/opencloud-eu/opencloud/services/notifications/pkg/email" + "github.com/opencloud-eu/opencloud/services/settings/pkg/store/defaults" +) + +func (s eventsNotifier) handleResourceMention(e ocEvents.ResourceMention, eventId string) { + logger := s.logger.With(). + Str("event", "Mention"). + Str("resourceid", e.Ref.GetResourceId().GetOpaqueId()). + Logger() + _ = logger + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + return + } + + ctx, err := utils.GetServiceUserContextWithContext(context.Background(), gatewayClient, s.serviceAccountID, s.serviceAccountSecret) + if err != nil { + logger.Error().Err(err).Msg("could not select next gateway client") + return + } + + var data = struct { + resourceLink string `validate:"required,url"` + resourceName string `validate:"required,min=1"` + author *user.User `validate:"required"` + recipients []*user.User `validate:"required,min=1"` + }{} + + // fill the data struct with the info we need to render the email + { + resourceInfo, err := s.getResourceInfo(ctx, e.Ref.GetResourceId(), nil) + if err != nil { + return + } + data.resourceName = resourceInfo.GetName() + + data.resourceLink, err = urlJoinPath(s.openCloudURL, "f", storagespace.FormatResourceID(resourceInfo.GetId())) + if err != nil { + logger.Error().Err(err).Msg("failed to generate resource link.") + return + } + + for _, userID := range append([]*user.UserId{e.Executant}, e.UserIDs...) { + switch u, err := s.getUser(ctx, userID); { + case err != nil: + logger.Error().Err(err).Msg("could not get user") + return + case userID.GetOpaqueId() == e.Executant.GetOpaqueId(): + data.author = u + default: + data.recipients = append(data.recipients, u) + } + } + + recipients := s.filter.execute(ctx, data.recipients, defaults.SettingUUIDProfileEventResourceMention) + recipientsInstant, recipientsDaily, recipientsInstantWeekly := s.splitter.execute(ctx, recipients) + recipientsInstant = append(recipientsInstant, s.userEventStore.persist(_intervalDaily, eventId, recipientsDaily)...) + recipientsInstant = append(recipientsInstant, s.userEventStore.persist(_intervalWeekly, eventId, recipientsInstantWeekly)...) + data.recipients = recipientsInstant + } + + if err := validate.Struct(data); err != nil { + logger.Error().Err(err).Msg("data struct validation failed") + return + } + + messages := make([]*channels.Message, len(data.recipients)) + for i, recipient := range data.recipients { + locale := l10n.MustGetUserLocale(ctx, recipient.GetId().GetOpaqueId(), "", s.valueService) + message, err := email.RenderEmailTemplate(email.Mention, locale, s.defaultLanguage, s.emailTemplatePath, s.translationPath, map[string]string{ + "AuthorName": data.author.GetDisplayName(), + "RecipientName": recipient.GetDisplayName(), + "ResourceName": data.resourceName, + "ResourceLink": data.resourceLink, + }) + if err != nil { + logger.Error().Err(err).Msg("could not render email-template") + return + } + + message.Sender = data.author.GetDisplayName() + message.Recipient = []string{recipient.GetMail()} + messages[i] = message + } + + s.send(ctx, messages) +} diff --git a/services/notifications/pkg/service/service.go b/services/notifications/pkg/service/service.go index 96d03cb2c0..65707bb355 100644 --- a/services/notifications/pkg/service/service.go +++ b/services/notifications/pkg/service/service.go @@ -10,9 +10,11 @@ import ( "sync" "sync/atomic" - ehsvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/eventhistory/v0" "go-micro.dev/v4/store" + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" + ehsvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/eventhistory/v0" + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -22,6 +24,9 @@ import ( "go-micro.dev/v4/metadata" "google.golang.org/protobuf/types/known/fieldmaskpb" + "github.com/opencloud-eu/reva/v2/pkg/events" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/opencloud-eu/opencloud/pkg/l10n" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/middleware" @@ -29,16 +34,13 @@ import ( "github.com/opencloud-eu/opencloud/services/notifications/pkg/channels" "github.com/opencloud-eu/opencloud/services/notifications/pkg/email" "github.com/opencloud-eu/opencloud/services/settings/pkg/store/defaults" - "github.com/opencloud-eu/reva/v2/pkg/events" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" ) // validate is the package level validator instance -var validate *validator.Validate - -func init() { - validate = validator.New() -} +var validate = validator.New( + validator.WithPrivateFieldValidation(), + validator.WithRequiredStructEnabled(), +) // Service should be named `Runner` type Service interface { @@ -131,6 +133,8 @@ EventLoop: s.handleScienceMeshInviteTokenGenerated(e) case events.SendEmailsEvent: s.sendGroupedEmailsJob(e, evt.ID) + case ocEvents.ResourceMention: + s.handleResourceMention(e, evt.ID) } }) diff --git a/services/proxy/pkg/config/defaults/defaultconfig.go b/services/proxy/pkg/config/defaults/defaultconfig.go index 5dd3541e18..e3f2e380c5 100644 --- a/services/proxy/pkg/config/defaults/defaultconfig.go +++ b/services/proxy/pkg/config/defaults/defaultconfig.go @@ -292,7 +292,12 @@ func DefaultPolicies() []config.Policy { SkipXAccessToken: true, }, { - Endpoint: "/collaboration/fonts/manage/", + Endpoint: "/collaboration/fonts/manage", + Service: "eu.opencloud.web.collaboration", + // Method: "POST" // toDo: fails with method, WHY??? + }, + { + Endpoint: "/collaboration/notify", Service: "eu.opencloud.web.collaboration", // Method: "POST" // toDo: fails with method, WHY??? }, diff --git a/services/settings/pkg/service/v0/service.go b/services/settings/pkg/service/v0/service.go index 37336393f6..bf8256de36 100644 --- a/services/settings/pkg/service/v0/service.go +++ b/services/settings/pkg/service/v0/service.go @@ -10,6 +10,12 @@ import ( cs3permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/leonelquinteros/gotext" + ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/status" + merrors "go-micro.dev/v4/errors" + "go-micro.dev/v4/metadata" + "google.golang.org/protobuf/types/known/emptypb" + "github.com/opencloud-eu/opencloud/pkg/l10n" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/middleware" @@ -20,11 +26,6 @@ import ( "github.com/opencloud-eu/opencloud/services/settings/pkg/settings" "github.com/opencloud-eu/opencloud/services/settings/pkg/store/defaults" metastore "github.com/opencloud-eu/opencloud/services/settings/pkg/store/metadata" - ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/status" - merrors "go-micro.dev/v4/errors" - "go-micro.dev/v4/metadata" - "google.golang.org/protobuf/types/known/emptypb" ) //go:embed l10n/locale @@ -708,6 +709,7 @@ func translateBundle(bundle *settingsmsg.Bundle, t *gotext.Locale) *settingsmsg. defaults.SettingUUIDProfileEventSpaceUnshared, defaults.SettingUUIDProfileEventSpaceMembershipExpired, defaults.SettingUUIDProfileEventSpaceDisabled, + defaults.SettingUUIDProfileEventResourceMention, defaults.SettingUUIDProfileEventSpaceDeleted: // translate event names ('Share Received', 'Share Removed', ...) set.DisplayName = t.Get(set.GetDisplayName(), []any{}...) diff --git a/services/settings/pkg/service/v0/servicedecorator.go b/services/settings/pkg/service/v0/servicedecorator.go index d639b73c90..4a41e4ad09 100644 --- a/services/settings/pkg/service/v0/servicedecorator.go +++ b/services/settings/pkg/service/v0/servicedecorator.go @@ -193,5 +193,6 @@ func getDefaultValueList() map[string]*settingsmsg.ValueWithIdentifier { defaults.SettingUUIDProfileEventSpaceDeleted: nil, defaults.SettingUUIDProfileEventPostprocessingStepFinished: nil, defaults.SettingUUIDProfileEmailSendingInterval: nil, + defaults.SettingUUIDProfileEventResourceMention: nil, } } diff --git a/services/settings/pkg/store/defaults/defaults.go b/services/settings/pkg/store/defaults/defaults.go index c65a3548c1..628c07e581 100644 --- a/services/settings/pkg/store/defaults/defaults.go +++ b/services/settings/pkg/store/defaults/defaults.go @@ -47,6 +47,8 @@ const ( SettingUUIDProfileEventSpaceDeleted = "094ceca9-5a00-40ba-bb1a-bbc7bccd39ee" // SettingUUIDProfileEventPostprocessingStepFinished is the hardcoded setting UUID for the send in mail setting SettingUUIDProfileEventPostprocessingStepFinished = "fe0a3011-d886-49c8-b797-33d02fa426ef" + // SettingUUIDProfileEventResourceMention is the hardcoded setting UUID for the send in mail setting + SettingUUIDProfileEventResourceMention = "08aaa973-a622-449d-97dc-3857160d1e97" ) // GenerateBundlesDefaultRoles bootstraps the default roles. @@ -79,6 +81,7 @@ func ServiceAccountBundle() *settingsmsg.Bundle { Settings: []*settingsmsg.Setting{ AccountManagementPermission(All), ChangeLogoPermission(All), + CollaborationPublishNotificationPermission(All), CollaborationManageFontsPermission(All), CreatePublicLinkPermission(All), CreateSharePermission(All), @@ -116,6 +119,7 @@ func generateBundleAdminRole() *settingsmsg.Bundle { AccountManagementPermission(All), AutoAcceptSharesPermission(Own), ChangeLogoPermission(All), + CollaborationPublishNotificationPermission(All), CollaborationManageFontsPermission(All), CreatePublicLinkPermission(All), CreateSharePermission(All), @@ -180,6 +184,7 @@ func generateBundleSpaceAdminRole() *settingsmsg.Bundle { ProfileEventPostprocessingStepFinishedPermission(Own), LanguageManagementPermission(Own), ListFavoritesPermission(Own), + CollaborationPublishNotificationPermission(All), ListSpacesPermission(All), ManageSpacePropertiesPermission(All), SelfManagementPermission(Own), @@ -218,6 +223,7 @@ func generateBundleUserRole() *settingsmsg.Bundle { ProfileEventPostprocessingStepFinishedPermission(Own), LanguageManagementPermission(Own), ListFavoritesPermission(Own), + CollaborationPublishNotificationPermission(All), SelfManagementPermission(Own), WriteFavoritesPermission(Own), }, @@ -345,6 +351,23 @@ func generateBundleProfileRequest() *settingsmsg.Bundle { }, }, }, + { + Id: SettingUUIDProfileEventResourceMention, + Name: "event-resource-mention-options", + DisplayName: TemplateResourceMention, + Description: TemplateResourceMentionDescription, + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_USER, + }, + Value: &settingsmsg.Setting_MultiChoiceCollectionValue{ + MultiChoiceCollectionValue: &settingsmsg.MultiChoiceCollection{ + Options: []*settingsmsg.MultiChoiceCollectionOption{ + &optionInAppTrue, + &optionMailTrue, + }, + }, + }, + }, { Id: SettingUUIDProfileEventSpaceShared, Name: "event-space-shared-options", diff --git a/services/settings/pkg/store/defaults/permissions.go b/services/settings/pkg/store/defaults/permissions.go index dec6aed3f0..ba81dd7914 100644 --- a/services/settings/pkg/store/defaults/permissions.go +++ b/services/settings/pkg/store/defaults/permissions.go @@ -67,7 +67,7 @@ func ChangeLogoPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Sett } } -// ManageFontsPermission is the permission to manage fonts +// CollaborationManageFontsPermission is the permission to manage fonts func CollaborationManageFontsPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { return &settingsmsg.Setting{ Id: "ed83fc10-1f54-4a9e-b5a7-fb517f5f3e01", @@ -86,6 +86,25 @@ func CollaborationManageFontsPermission(c settingsmsg.Permission_Constraint) *se } } +// CollaborationPublishNotificationPermission is the permission to manage fonts +func CollaborationPublishNotificationPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { + return &settingsmsg.Setting{ + Id: "43e5948e-8238-41d6-9ef1-f259f00591db", + Name: "Collaboration.Notification.Publish", + DisplayName: "Publish collaboration notifications", + Description: "This permission permits to publish collaboration related notifications.", + Resource: &settingsmsg.Resource{ + Type: settingsmsg.Resource_TYPE_SYSTEM, + }, + Value: &settingsmsg.Setting_PermissionValue{ + PermissionValue: &settingsmsg.Permission{ + Operation: settingsmsg.Permission_OPERATION_READWRITE, + Constraint: c, + }, + }, + } +} + // CreatePublicLinkPermission is the permission to create public links func CreatePublicLinkPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { return &settingsmsg.Setting{ diff --git a/services/settings/pkg/store/defaults/templates.go b/services/settings/pkg/store/defaults/templates.go index 57252abef0..bc07a0d255 100644 --- a/services/settings/pkg/store/defaults/templates.go +++ b/services/settings/pkg/store/defaults/templates.go @@ -12,6 +12,10 @@ var ( TemplateShareRemoved = l10n.Template("Share Removed") // description of the notification option 'Share Removed' TemplateShareRemovedDescription = l10n.Template("Notify when a received share has been removed") + // name of the notification option 'Resource Mention' + TemplateResourceMention = l10n.Template("Resource Mention") + // description of the notification option 'Resource Mention' + TemplateResourceMentionDescription = l10n.Template("Notify on resource mentions") // name of the notification option 'Share Expired' TemplateShareExpired = l10n.Template("Share Expired") // description of the notification option 'Share Expired' diff --git a/services/userlog/pkg/command/server.go b/services/userlog/pkg/command/server.go index 445bb6810e..4aacb7a8f0 100644 --- a/services/userlog/pkg/command/server.go +++ b/services/userlog/pkg/command/server.go @@ -6,6 +6,7 @@ import ( "os/signal" "github.com/opencloud-eu/opencloud/pkg/config/configlog" + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" "github.com/opencloud-eu/opencloud/pkg/generators" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/registry" @@ -45,6 +46,9 @@ var _registeredEvents = []events.Unmarshaller{ events.ShareCreated{}, events.ShareRemoved{}, events.ShareExpired{}, + + // misc + ocEvents.ResourceMention{}, } // Server is the entrypoint for the server command. diff --git a/services/userlog/pkg/service/conversion.go b/services/userlog/pkg/service/conversion.go index f235baecc8..5a6547ee91 100644 --- a/services/userlog/pkg/service/conversion.go +++ b/services/userlog/pkg/service/conversion.go @@ -14,11 +14,13 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - "github.com/opencloud-eu/opencloud/pkg/l10n" "github.com/opencloud-eu/reva/v2/pkg/events" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" "github.com/opencloud-eu/reva/v2/pkg/storagespace" "github.com/opencloud-eu/reva/v2/pkg/utils" + + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" + "github.com/opencloud-eu/opencloud/pkg/l10n" ) //go:embed l10n/locale @@ -115,7 +117,12 @@ func (c *Converter) ConvertEvent(eventid string, event any) (OC10Notification, e return c.shareMessage(eventid, ShareExpired, ev.ShareOwner, ev.ItemID, ev.ShareID, ev.ExpiredAt) case events.ShareRemoved: return c.shareMessage(eventid, ShareRemoved, ev.Executant, ev.ItemID, ev.ShareID, ev.Timestamp) + + // misc + case ocEvents.ResourceMention: + return c.resourceMention(eventid, Mention, ev.Executant, ev.Ref.GetResourceId(), ev.Timestamp) } + } // ConvertGlobalEvent converts a global event to an OC10Notification @@ -199,6 +206,40 @@ func (c *Converter) spaceMessage(eventid string, nt NotificationTemplate, execut }, nil } +func (c *Converter) resourceMention(eventid string, nt NotificationTemplate, executant *user.UserId, resourceid *storageprovider.ResourceId, ts time.Time) (OC10Notification, error) { + usr, err := c.getUser(context.Background(), executant) + if err != nil { + return OC10Notification{}, err + } + + info, err := c.getResource(c.serviceAccountContext, resourceid) + if err != nil { + return OC10Notification{}, err + } + + subj, subjraw, msg, msgraw, err := composeMessage(nt, c.locale, c.defaultLanguage, c.translationPath, map[string]any{ + "username": usr.GetDisplayName(), + "resourcename": info.GetName(), + }) + if err != nil { + return OC10Notification{}, err + } + + return OC10Notification{ + EventID: eventid, + Service: c.serviceName, + UserName: usr.GetUsername(), + Timestamp: ts.Format(time.RFC3339Nano), + ResourceID: storagespace.FormatResourceID(info.GetId()), + ResourceType: "mention", + Subject: subj, + SubjectRaw: subjraw, + Message: msg, + MessageRaw: msgraw, + MessageDetails: generateDetails(usr, nil, info, nil), + }, nil +} + func (c *Converter) shareMessage(eventid string, nt NotificationTemplate, executant *user.UserId, resourceid *storageprovider.ResourceId, shareid *collaboration.ShareId, ts time.Time) (OC10Notification, error) { usr, err := c.getUser(context.Background(), executant) if err != nil { diff --git a/services/userlog/pkg/service/filter.go b/services/userlog/pkg/service/filter.go index a7727d85db..f45ed18a8d 100644 --- a/services/userlog/pkg/service/filter.go +++ b/services/userlog/pkg/service/filter.go @@ -5,12 +5,14 @@ import ( "errors" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + "github.com/opencloud-eu/reva/v2/pkg/events" + micrometadata "go-micro.dev/v4/metadata" + + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/middleware" settingssvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/settings/v0" "github.com/opencloud-eu/opencloud/services/settings/pkg/store/defaults" - "github.com/opencloud-eu/reva/v2/pkg/events" - micrometadata "go-micro.dev/v4/metadata" ) type userlogFilter struct { @@ -61,6 +63,8 @@ func (ulf userlogFilter) filterUsersBySettings(ctx context.Context, users []stri settingId = defaults.SettingUUIDProfileEventSpaceDisabled case events.SpaceDeleted: settingId = defaults.SettingUUIDProfileEventSpaceDeleted + case ocEvents.ResourceMention: + settingId = defaults.SettingUUIDProfileEventResourceMention default: // event that cannot be disabled return users diff --git a/services/userlog/pkg/service/service.go b/services/userlog/pkg/service/service.go index b58538aad7..957a84446f 100644 --- a/services/userlog/pkg/service/service.go +++ b/services/userlog/pkg/service/service.go @@ -17,6 +17,7 @@ import ( "go-micro.dev/v4/store" "go.opentelemetry.io/otel/trace" + ocEvents "github.com/opencloud-eu/opencloud/pkg/events" "github.com/opencloud-eu/opencloud/pkg/l10n" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/pkg/roles" @@ -168,6 +169,11 @@ func (ul *UserlogService) processEvent(event events.Event) { case events.SpaceShared: executant = e.Executant users, err = utils.ResolveID(ctx, e.GranteeUserID, e.GranteeGroupID, gwc) + case ocEvents.ResourceMention: + executant = e.Executant + for _, userID := range e.UserIDs { + users = append(users, userID.GetOpaqueId()) + } case events.SpaceUnshared: executant = e.Executant users, err = utils.ResolveID(ctx, e.GranteeUserID, e.GranteeGroupID, gwc) diff --git a/services/userlog/pkg/service/templates.go b/services/userlog/pkg/service/templates.go index e7de3b1c9d..6b244f2da5 100644 --- a/services/userlog/pkg/service/templates.go +++ b/services/userlog/pkg/service/templates.go @@ -49,6 +49,11 @@ var ( Message: l10n.Template("{user} unshared {resource} with you"), } + Mention = NotificationTemplate{ + Subject: l10n.Template("You have been mentioned"), + Message: l10n.Template("{user} mentioned you in {resource}"), + } + ShareExpired = NotificationTemplate{ Subject: l10n.Template("Share expired"), Message: l10n.Template("Access to {resource} expired"), From 00138363846566bf5a6ffd4c7c491d933c4d3f4d Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 10 Jun 2026 15:02:33 +0200 Subject: [PATCH 3/6] chore: cleanup unnecessary changes --- .bingo/go-xgettext.mod | 2 ++ .gitignore | 6 ------ services/web/Makefile | 12 +++--------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.bingo/go-xgettext.mod b/.bingo/go-xgettext.mod index 8e3c6210b5..b14946a0b8 100644 --- a/.bingo/go-xgettext.mod +++ b/.bingo/go-xgettext.mod @@ -3,3 +3,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.23.4 require github.com/gosexy/gettext v0.0.0-20160830220431-74466a0a0c4a // go-xgettext + +require github.com/jessevdk/go-flags v1.6.1 // indirect diff --git a/.gitignore b/.gitignore index 79d46d1d89..917b48e04c 100644 --- a/.gitignore +++ b/.gitignore @@ -66,9 +66,3 @@ go.work.sum # example deployments **/opencloud-sandbox-* - -# web apps -!./services/web/assets/ -!./services/web/assets/apps/ -!./services/web/assets/apps/collaboration-settings -!./services/web/assets/apps/collaboration-settings/** diff --git a/services/web/Makefile b/services/web/Makefile index 453122a865..7835ac6bbe 100644 --- a/services/web/Makefile +++ b/services/web/Makefile @@ -13,10 +13,11 @@ include ../../.make/release.mk include ../../.make/docs.mk .PHONY: node-generate-dev -node-generate-dev: pull-assets build-apps +node-generate-dev: pull-assets .PHONY: node-generate-prod -node-generate-prod: download-assets build-apps +node-generate-prod: download-assets + .PHONY: pull-assets pull-assets: @@ -42,13 +43,6 @@ download-assets: git clean -xfd assets curl --fail -slL -o- https://github.com/opencloud-eu/web/releases/download/$(WEB_ASSETS_VERSION)/web.tar.gz | tar xzf - -C assets/core/ -.PHONY: build-apps -build-apps: - @for dir in ./assets/apps/*; do \ - echo "📦 Installing in $$dir"; \ - (cd "$$dir" && pnpm install && pnpm build) || exit 1; \ - done - .PHONY: ci-node-save-licenses ci-node-save-licenses: @mkdir -p ../../third-party-licenses/node/web From 35766b37d784c13ced77698c474f6424a5748c4a Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Wed, 10 Jun 2026 21:22:31 +0200 Subject: [PATCH 4/6] fix: missing returns --- services/collaboration/pkg/command/server.go | 11 +++++------ services/collaboration/pkg/font/service.go | 2 ++ services/collaboration/pkg/notification/service.go | 1 + services/notifications/pkg/service/resource.go | 1 - services/settings/pkg/store/defaults/permissions.go | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index f028e36ded..d8a6199ba1 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -159,7 +159,7 @@ func Server(cfg *config.Config) *cobra.Command { return err } - service, err := font.NewService( + fontService, err = font.NewService( font.ServiceOptions{}. WithFontFS(fontFS). WithRootURI(fontServiceRootURI). @@ -170,8 +170,6 @@ func Server(cfg *config.Config) *cobra.Command { if err != nil { return err } - - fontService = service } var notificationService notification.Service @@ -181,15 +179,16 @@ func Server(cfg *config.Config) *cobra.Command { if err != nil { return err } - service, err := notification.NewService( + notificationService, err = notification.NewService( notification.ServiceOptions{}. WithLogger(logger). WithGatewaySelector(gatewaySelector). WithEventPublisher(natsStream). WithMachineAuthAPIKey(cfg.MachineAuthAPIKey), ) - - notificationService = service + if err != nil { + return err + } } // start HTTP server diff --git a/services/collaboration/pkg/font/service.go b/services/collaboration/pkg/font/service.go index d6ed2ca528..20300853b2 100644 --- a/services/collaboration/pkg/font/service.go +++ b/services/collaboration/pkg/font/service.go @@ -89,6 +89,7 @@ func (s Service) DeleteFont(w http.ResponseWriter, r *http.Request) { gatewayClient, err := s.gatewaySelector.Next() if err != nil { w.WriteHeader(http.StatusInternalServerError) + return } _, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationManageFonts) @@ -282,6 +283,7 @@ func (s Service) UploadFont(w http.ResponseWriter, r *http.Request) { gatewayClient, err := s.gatewaySelector.Next() if err != nil { w.WriteHeader(http.StatusInternalServerError) + return } _, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationManageFonts) diff --git a/services/collaboration/pkg/notification/service.go b/services/collaboration/pkg/notification/service.go index 97eff22e95..bd1bac80a3 100644 --- a/services/collaboration/pkg/notification/service.go +++ b/services/collaboration/pkg/notification/service.go @@ -72,6 +72,7 @@ func (s Service) HandleNotification(w http.ResponseWriter, r *http.Request) { gatewayClient, err := s.gatewaySelector.Next() if err != nil { w.WriteHeader(http.StatusInternalServerError) + return } requestUser, canManage, err := collaboration.CheckPermissions(gatewayClient, r.Context(), collaboration.PermissionCollaborationPublishNotification) diff --git a/services/notifications/pkg/service/resource.go b/services/notifications/pkg/service/resource.go index 3138f51ebc..6fe13fb23f 100644 --- a/services/notifications/pkg/service/resource.go +++ b/services/notifications/pkg/service/resource.go @@ -19,7 +19,6 @@ func (s eventsNotifier) handleResourceMention(e ocEvents.ResourceMention, eventI Str("event", "Mention"). Str("resourceid", e.Ref.GetResourceId().GetOpaqueId()). Logger() - _ = logger gatewayClient, err := s.gatewaySelector.Next() if err != nil { return diff --git a/services/settings/pkg/store/defaults/permissions.go b/services/settings/pkg/store/defaults/permissions.go index ba81dd7914..4f80c1d124 100644 --- a/services/settings/pkg/store/defaults/permissions.go +++ b/services/settings/pkg/store/defaults/permissions.go @@ -86,7 +86,7 @@ func CollaborationManageFontsPermission(c settingsmsg.Permission_Constraint) *se } } -// CollaborationPublishNotificationPermission is the permission to manage fonts +// CollaborationPublishNotificationPermission is the permission to publish collaboration notifications func CollaborationPublishNotificationPermission(c settingsmsg.Permission_Constraint) *settingsmsg.Setting { return &settingsmsg.Setting{ Id: "43e5948e-8238-41d6-9ef1-f259f00591db", From 84b96f6f8c429c1fdfacabbe52eb9d09bea30b0c Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 10 Jun 2026 22:42:52 +0200 Subject: [PATCH 5/6] fix: duplicated fontFS initialization --- services/collaboration/pkg/command/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/collaboration/pkg/command/server.go b/services/collaboration/pkg/command/server.go index d8a6199ba1..e5196fb0a3 100644 --- a/services/collaboration/pkg/command/server.go +++ b/services/collaboration/pkg/command/server.go @@ -154,7 +154,7 @@ func Server(cfg *config.Config) *cobra.Command { } fontServiceRootURI, err := url.JoinPath(cfg.Commons.OpenCloudURL, "/collaboration/fonts") - if err := fontFS.MkdirAll("/", 0o755); err != nil { + if err != nil { logger.Error().Err(err).Msg("Failed to build font service root uri") return err } From 61eed98f07eabafd5fa01fb753b149ff7341e229 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Thu, 11 Jun 2026 10:50:29 +0200 Subject: [PATCH 6/6] add static OC_MACHINE_AUTH_API_KEY Signed-off-by: Christian Richter --- .woodpecker.star | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.woodpecker.star b/.woodpecker.star index be3f297434..f51cc45b8e 100644 --- a/.woodpecker.star +++ b/.woodpecker.star @@ -71,6 +71,7 @@ OC_DOMAIN = "%s:9200" % OC_SERVER_NAME FED_OC_SERVER_NAME = "federation-opencloud-server" OC_FED_URL = "https://%s:10200" % FED_OC_SERVER_NAME OC_FED_DOMAIN = "%s:10200" % FED_OC_SERVER_NAME +MACHINE_AUTH_API_KEY = "fjsdlfgkjsdlktgersoiulersiltjlekir5[345;lesirtuwe542345wert" event = { "base": { @@ -2337,6 +2338,7 @@ def opencloudServer(storage = "decomposed", depends_on = [], deploy_type = "", e "WEBDAV_DEBUG_ADDR": "0.0.0.0:9119", "WEBFINGER_DEBUG_ADDR": "0.0.0.0:9279", "STORAGE_USERS_POSIX_SCAN_DEBOUNCE_DELAY": 0, + "OC_MACHINE_AUTH_API_KEY": MACHINE_AUTH_API_KEY, } if storage == "posix": @@ -3216,6 +3218,7 @@ def wopiCollaborationService(name): "OC_JWT_SECRET": "some-opencloud-jwt-secret", "COLLABORATION_WOPI_SECRET": "some-wopi-secret", "COLLABORATION_EVENTS_ENDPOINT": "%s:9233" % OC_SERVER_NAME, + "OC_MACHINE_AUTH_API_KEY": MACHINE_AUTH_API_KEY, } if name == "collabora":