mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-06 04:09:40 -06:00
When using the metadata storage (the current default) the default role assignments were recreated at every start of the settings service. Leading to duplicated role assignments Fixes: #3432
166 lines
3.9 KiB
Go
166 lines
3.9 KiB
Go
// Package store implements the go-micro store interface
|
|
package store
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/cs3org/reva/v2/pkg/storage/utils/metadata"
|
|
"github.com/gofrs/uuid"
|
|
olog "github.com/owncloud/ocis/v2/ocis-pkg/log"
|
|
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
|
"github.com/owncloud/ocis/v2/services/settings/pkg/config"
|
|
"github.com/owncloud/ocis/v2/services/settings/pkg/settings"
|
|
"github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults"
|
|
)
|
|
|
|
var (
|
|
// Name is the default name for the settings store
|
|
Name = "ocis-settings"
|
|
managerName = "metadata"
|
|
settingsSpaceID = "f1bdd61a-da7c-49fc-8203-0558109d1b4f" // uuid.Must(uuid.NewV4()).String()
|
|
rootFolderLocation = "settings"
|
|
bundleFolderLocation = "settings/bundles"
|
|
accountsFolderLocation = "settings/accounts"
|
|
valuesFolderLocation = "settings/values"
|
|
)
|
|
|
|
// MetadataClient is the interface to talk to metadata service
|
|
type MetadataClient interface {
|
|
SimpleDownload(ctx context.Context, id string) ([]byte, error)
|
|
SimpleUpload(ctx context.Context, id string, content []byte) error
|
|
Delete(ctx context.Context, id string) error
|
|
ReadDir(ctx context.Context, id string) ([]string, error)
|
|
MakeDirIfNotExist(ctx context.Context, id string) error
|
|
Init(ctx context.Context, id string) error
|
|
}
|
|
|
|
// Store interacts with the filesystem to manage settings information
|
|
type Store struct {
|
|
Logger olog.Logger
|
|
|
|
mdc MetadataClient
|
|
cfg *config.Config
|
|
|
|
l *sync.Mutex
|
|
}
|
|
|
|
// Init initialize the store once, later calls are noops
|
|
func (s *Store) Init() {
|
|
if s.mdc != nil {
|
|
return
|
|
}
|
|
|
|
s.l.Lock()
|
|
defer s.l.Unlock()
|
|
|
|
if s.mdc != nil {
|
|
return
|
|
}
|
|
|
|
mdc := &CachedMDC{next: NewMetadataClient(s.cfg.Metadata)}
|
|
if err := s.initMetadataClient(mdc); err != nil {
|
|
s.Logger.Error().Err(err).Msg("error initializing metadata client")
|
|
}
|
|
}
|
|
|
|
// New creates a new store
|
|
func New(cfg *config.Config) settings.Manager {
|
|
s := Store{
|
|
Logger: olog.NewLogger(
|
|
olog.Color(cfg.Log.Color),
|
|
olog.Pretty(cfg.Log.Pretty),
|
|
olog.Level(cfg.Log.Level),
|
|
olog.File(cfg.Log.File),
|
|
),
|
|
cfg: cfg,
|
|
l: &sync.Mutex{},
|
|
}
|
|
|
|
return &s
|
|
}
|
|
|
|
// NewMetadataClient returns the MetadataClient
|
|
func NewMetadataClient(cfg config.Metadata) MetadataClient {
|
|
mdc, err := metadata.NewCS3Storage(cfg.GatewayAddress, cfg.StorageAddress, cfg.SystemUserID, cfg.SystemUserIDP, cfg.SystemUserAPIKey)
|
|
if err != nil {
|
|
log.Fatal("error connecting to mdc:", err)
|
|
}
|
|
return mdc
|
|
|
|
}
|
|
|
|
// we need to lazy initialize the MetadataClient because metadata service might not be ready
|
|
func (s *Store) initMetadataClient(mdc MetadataClient) error {
|
|
ctx := context.TODO()
|
|
err := mdc.Init(ctx, settingsSpaceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, p := range []string{
|
|
rootFolderLocation,
|
|
accountsFolderLocation,
|
|
bundleFolderLocation,
|
|
valuesFolderLocation,
|
|
} {
|
|
err = mdc.MakeDirIfNotExist(ctx, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
for _, p := range s.cfg.Bundles {
|
|
b, err := json.Marshal(p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = mdc.SimpleUpload(ctx, bundlePath(p.Id), b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
for _, p := range defaults.DefaultRoleAssignments(s.cfg) {
|
|
accountUUID := p.AccountUuid
|
|
roleID := p.RoleId
|
|
err = mdc.MakeDirIfNotExist(ctx, accountPath(accountUUID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
assIDs, err := mdc.ReadDir(ctx, accountPath(accountUUID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(assIDs) > 0 {
|
|
// There is already a role assignment for this ID, skip to the next
|
|
continue
|
|
}
|
|
|
|
ass := &settingsmsg.UserRoleAssignment{
|
|
Id: uuid.Must(uuid.NewV4()).String(),
|
|
AccountUuid: accountUUID,
|
|
RoleId: roleID,
|
|
}
|
|
|
|
b, err := json.Marshal(ass)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = mdc.SimpleUpload(ctx, assignmentPath(accountUUID, ass.Id), b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
s.mdc = mdc
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
settings.Registry[managerName] = New
|
|
}
|