mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-01 18:01:23 -05:00
175 lines
4.5 KiB
Go
175 lines
4.5 KiB
Go
// Package store implements the go-micro store interface
|
|
package store
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"sync"
|
|
|
|
"github.com/gofrs/uuid"
|
|
"github.com/owncloud/ocis/settings/pkg/proto/v0"
|
|
)
|
|
|
|
var m = &sync.RWMutex{}
|
|
|
|
// ListBundles returns all bundles in the dataPath folder that match the given type.
|
|
func (s Store) ListBundles(bundleType proto.Bundle_Type, bundleIDs []string) ([]*proto.Bundle, error) {
|
|
// FIXME: list requests should be ran against a cache, not FS
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
bundlesFolder := s.buildFolderPathForBundles(false)
|
|
bundleFiles, err := ioutil.ReadDir(bundlesFolder)
|
|
if err != nil {
|
|
return []*proto.Bundle{}, nil
|
|
}
|
|
|
|
records := make([]*proto.Bundle, 0, len(bundleFiles))
|
|
for _, bundleFile := range bundleFiles {
|
|
record := proto.Bundle{}
|
|
err = s.parseRecordFromFile(&record, filepath.Join(bundlesFolder, bundleFile.Name()))
|
|
if err != nil {
|
|
s.Logger.Warn().Msgf("error reading %v", bundleFile)
|
|
continue
|
|
}
|
|
if record.Type != bundleType {
|
|
continue
|
|
}
|
|
if len(bundleIDs) > 0 && !containsStr(record.Id, bundleIDs) {
|
|
continue
|
|
}
|
|
records = append(records, &record)
|
|
}
|
|
|
|
return records, nil
|
|
}
|
|
|
|
// containsStr checks if the strs slice contains str
|
|
func containsStr(str string, strs []string) bool {
|
|
for _, s := range strs {
|
|
if s == str {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ReadBundle tries to find a bundle by the given id within the dataPath.
|
|
func (s Store) ReadBundle(bundleID string) (*proto.Bundle, error) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
filePath := s.buildFilePathForBundle(bundleID, false)
|
|
record := proto.Bundle{}
|
|
if err := s.parseRecordFromFile(&record, filePath); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.Logger.Debug().Msgf("read contents from file: %v", filePath)
|
|
return &record, nil
|
|
}
|
|
|
|
// ReadSetting tries to find a setting by the given id within the dataPath.
|
|
func (s Store) ReadSetting(settingID string) (*proto.Setting, error) {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
bundles, err := s.ListBundles(proto.Bundle_TYPE_DEFAULT, []string{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, bundle := range bundles {
|
|
for _, setting := range bundle.Settings {
|
|
if setting.Id == settingID {
|
|
return setting, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("could not read setting: %v", settingID)
|
|
}
|
|
|
|
// WriteBundle writes the given record into a file within the dataPath.
|
|
func (s Store) WriteBundle(record *proto.Bundle) (*proto.Bundle, error) {
|
|
// FIXME: locking should happen on the file here, not globally.
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
if record.Id == "" {
|
|
record.Id = uuid.Must(uuid.NewV4()).String()
|
|
}
|
|
filePath := s.buildFilePathForBundle(record.Id, true)
|
|
if err := s.writeRecordToFile(record, filePath); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.Logger.Debug().Msgf("request contents written to file: %v", filePath)
|
|
return record, nil
|
|
}
|
|
|
|
// AddSettingToBundle adds the given setting to the bundle with the given bundleID.
|
|
func (s Store) AddSettingToBundle(bundleID string, setting *proto.Setting) (*proto.Setting, error) {
|
|
bundle, err := s.ReadBundle(bundleID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if setting.Id == "" {
|
|
setting.Id = uuid.Must(uuid.NewV4()).String()
|
|
}
|
|
setSetting(bundle, setting)
|
|
_, err = s.WriteBundle(bundle)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return setting, nil
|
|
}
|
|
|
|
// RemoveSettingFromBundle removes the setting from the bundle with the given ids.
|
|
func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error {
|
|
bundle, err := s.ReadBundle(bundleID)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if ok := removeSetting(bundle, settingID); ok {
|
|
if _, err := s.WriteBundle(bundle); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// indexOfSetting finds the index of the given setting within the given bundle.
|
|
// returns -1 if the setting was not found.
|
|
func indexOfSetting(bundle *proto.Bundle, settingID string) int {
|
|
for index := range bundle.Settings {
|
|
s := bundle.Settings[index]
|
|
if s.Id == settingID {
|
|
return index
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// setSetting will append or overwrite the given setting within the given bundle
|
|
func setSetting(bundle *proto.Bundle, setting *proto.Setting) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
index := indexOfSetting(bundle, setting.Id)
|
|
if index == -1 {
|
|
bundle.Settings = append(bundle.Settings, setting)
|
|
} else {
|
|
bundle.Settings[index] = setting
|
|
}
|
|
}
|
|
|
|
// removeSetting will remove the given setting from the given bundle
|
|
func removeSetting(bundle *proto.Bundle, settingID string) bool {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
index := indexOfSetting(bundle, settingID)
|
|
if index == -1 {
|
|
return false
|
|
}
|
|
bundle.Settings = append(bundle.Settings[:index], bundle.Settings[index+1:]...)
|
|
return true
|
|
}
|