From fe7956aa832bec8c266c8c2e9ca32420beb27262 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Tue, 23 Sep 2025 08:19:29 +0200 Subject: [PATCH] Block writes operations in read-only mode on the server --- server/cmd/server.go | 17 ++++++++---- server/read_only_space_primitives.go | 41 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 server/read_only_space_primitives.go diff --git a/server/cmd/server.go b/server/cmd/server.go index bca0d20c..d6eb8113 100644 --- a/server/cmd/server.go +++ b/server/cmd/server.go @@ -73,6 +73,17 @@ func buildConfig(bundledFiles fs.FS, args []string) *server.ServerConfig { var spacePrimitives server.SpacePrimitives spacePrimitives, err := server.NewDiskSpacePrimitives(rootSpaceConfig.SpaceFolderPath, rootSpaceConfig.GitIgnore) + rootSpaceConfig.ReadOnlyMode = os.Getenv("SB_READ_ONLY") != "" + + if rootSpaceConfig.ReadOnlyMode { + log.Println("Starting in read-only mode.") + } + + if rootSpaceConfig.ReadOnlyMode { + // Wrap the space primitives in read only mode + spacePrimitives = server.NewReadOnlySpacePrimitives(spacePrimitives) + } + if err != nil { log.Fatal(err) } @@ -109,8 +120,6 @@ func buildConfig(bundledFiles fs.FS, args []string) *server.ServerConfig { pieces[0], rootSpaceConfig.Auth.LockoutLimit, rootSpaceConfig.Auth.LockoutTime) } - rootSpaceConfig.ReadOnlyMode = os.Getenv("SB_READ_ONLY") != "" - if os.Getenv("SB_NAME") != "" { rootSpaceConfig.SpaceName = os.Getenv("SB_NAME") } @@ -119,10 +128,6 @@ func buildConfig(bundledFiles fs.FS, args []string) *server.ServerConfig { rootSpaceConfig.SpaceDescription = os.Getenv("SB_DESCRIPTION") } - if rootSpaceConfig.ReadOnlyMode { - log.Println("Starting in read-only mode.") - } - if os.Getenv("SB_URL_PREFIX") != "" { hostUrlPrefix := os.Getenv("SB_URL_PREFIX") // Normalize the host URL prefix (if set) diff --git a/server/read_only_space_primitives.go b/server/read_only_space_primitives.go new file mode 100644 index 00000000..e4f42c29 --- /dev/null +++ b/server/read_only_space_primitives.go @@ -0,0 +1,41 @@ +package server + +import ( + "errors" +) + +type ReadOnlySpacePrimitives struct { + wrapped SpacePrimitives +} + +var _ SpacePrimitives = &ReadOnlySpacePrimitives{} +var NotAllowedError = errors.New("Not allowed") + +func NewReadOnlySpacePrimitives(wrapped SpacePrimitives) *ReadOnlySpacePrimitives { + return &ReadOnlySpacePrimitives{wrapped: wrapped} +} + +// FetchFileList retrieves a list of all files in the space +func (ro *ReadOnlySpacePrimitives) FetchFileList() ([]FileMeta, error) { + return ro.wrapped.FetchFileList() +} + +// GetFileMeta retrieves metadata for a specific file +func (ro *ReadOnlySpacePrimitives) GetFileMeta(path string) (FileMeta, error) { + return ro.wrapped.GetFileMeta(path) +} + +// ReadFile reads a file and returns its data and metadata +func (ro *ReadOnlySpacePrimitives) ReadFile(path string) ([]byte, FileMeta, error) { + return ro.wrapped.ReadFile(path) +} + +// WriteFile returns an error since this is a read-only implementation +func (ro *ReadOnlySpacePrimitives) WriteFile(path string, data []byte, meta *FileMeta) (FileMeta, error) { + return FileMeta{}, NotAllowedError +} + +// DeleteFile returns an error since this is a read-only implementation +func (ro *ReadOnlySpacePrimitives) DeleteFile(path string) error { + return NotAllowedError +}