diff --git a/accounts/pkg/storage/cs3.go b/accounts/pkg/storage/cs3.go index f628f538f4..c50f68be52 100644 --- a/accounts/pkg/storage/cs3.go +++ b/accounts/pkg/storage/cs3.go @@ -6,15 +6,15 @@ import ( "path" "path/filepath" - "github.com/cs3org/reva/pkg/auth/scope" - user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" v1beta11 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/auth/scope" revactx "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/utils" "github.com/owncloud/ocis/accounts/pkg/config" "github.com/owncloud/ocis/accounts/pkg/proto/v0" olog "github.com/owncloud/ocis/ocis-pkg/log" @@ -22,16 +22,12 @@ import ( "google.golang.org/grpc/metadata" ) -const ( - storageMountPath = "/meta" -) - // CS3Repo provides a cs3 implementation of the Repo interface type CS3Repo struct { cfg *config.Config tm token.Manager storageProvider provider.ProviderAPIClient - metadataStorage metadatastorage.MetadataStorage + metadataStorage *metadatastorage.MetadataStorage } // NewCS3Repo creates a new cs3 repo @@ -54,12 +50,22 @@ func NewCS3Repo(cfg *config.Config) (Repo, error) { return nil, err } - return CS3Repo{ + r := CS3Repo{ cfg: cfg, tm: tokenManager, storageProvider: client, - metadataStorage: ms, - }, nil + metadataStorage: &ms, + } + + ctx, err := r.getAuthenticatedContext(context.Background()) + if err != nil { + return nil, err + } + if err := ms.Init(ctx, cfg.ServiceUser); err != nil { + return nil, err + } + + return r, nil } // WriteAccount writes an account via cs3 and modifies the provided account (e.g. with a generated id). @@ -102,7 +108,8 @@ func (r CS3Repo) LoadAccounts(ctx context.Context, a *[]*proto.Account) (err err res, err := r.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, accountsFolder), + ResourceId: r.metadataStorage.SpaceRoot, + Path: utils.MakeRelativePath(accountsFolder), }, }) if err != nil { @@ -142,7 +149,8 @@ func (r CS3Repo) DeleteAccount(ctx context.Context, id string) (err error) { resp, err := r.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, accountsFolder, id), + ResourceId: r.metadataStorage.SpaceRoot, + Path: utils.MakeRelativePath(filepath.Join("/", accountsFolder, id)), }, }) @@ -197,7 +205,8 @@ func (r CS3Repo) LoadGroups(ctx context.Context, g *[]*proto.Group) (err error) res, err := r.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, groupsFolder), + ResourceId: r.metadataStorage.SpaceRoot, + Path: utils.MakeRelativePath(groupsFolder), }, }) if err != nil { @@ -237,7 +246,8 @@ func (r CS3Repo) DeleteGroup(ctx context.Context, id string) (err error) { resp, err := r.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, groupsFolder, id), + ResourceId: r.metadataStorage.SpaceRoot, + Path: utils.MakeRelativePath(filepath.Join(groupsFolder, id)), }, }) @@ -289,13 +299,14 @@ func (r CS3Repo) groupURL(id string) string { } func (r CS3Repo) makeRootDirIfNotExist(ctx context.Context, folder string) error { - return MakeDirIfNotExist(ctx, r.storageProvider, folder) + return MakeDirIfNotExist(ctx, r.storageProvider, r.metadataStorage.SpaceRoot, folder) } // MakeDirIfNotExist will create a root node in the metadata storage. Requires an authenticated context. -func MakeDirIfNotExist(ctx context.Context, sp provider.ProviderAPIClient, folder string) error { +func MakeDirIfNotExist(ctx context.Context, sp provider.ProviderAPIClient, root *provider.ResourceId, folder string) error { var rootPathRef = &provider.Reference{ - Path: path.Join(storageMountPath, folder), + ResourceId: root, + Path: utils.MakeRelativePath(folder), } resp, err := sp.Stat(ctx, &provider.StatRequest{ diff --git a/go.mod b/go.mod index 6446ea3517..d28bb821b0 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/gofrs/uuid v4.2.0+incompatible github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 + github.com/google/uuid v1.3.0 github.com/gookit/config/v2 v2.0.27 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.2 @@ -76,6 +77,7 @@ require ( require ( contrib.go.opencensus.io/exporter/prometheus v0.4.0 // indirect github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect + github.com/BurntSushi/toml v0.4.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect @@ -141,7 +143,6 @@ require ( github.com/gomodule/redigo v1.8.6 // indirect github.com/google/go-cmp v0.5.6 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/gookit/goutil v0.4.0 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -213,7 +214,6 @@ require ( github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/steveyen/gtreap v0.1.0 // indirect - github.com/studio-b12/gowebdav v0.0.0-20211109083228-3f8721cd4b6f // indirect github.com/tus/tusd v1.8.0 // indirect github.com/wk8/go-ordered-map v0.2.0 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect @@ -242,3 +242,8 @@ require ( stash.kopano.io/kgol/kcc-go/v5 v5.0.1 // indirect stash.kopano.io/kgol/oidc-go v0.3.2 // indirect ) + +//replace github.com/cs3org/reva => github.com/cs3org/reva v1.16.1-0.20211208164450-3abd76eecf8b +//replace github.com/cs3org/reva => ../reva + +replace github.com/cs3org/reva => github.com/cs3org/reva v1.16.1-0.20220111150347-1b21aefbf8db diff --git a/go.sum b/go.sum index d5e24ed451..eefeacae18 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,7 @@ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzS github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ= github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CiscoM31/godata v1.0.5 h1:AITXpa/5ybXEq59A0nqUGiS7ZXVJnQtFw5o09tyN/UA= @@ -323,8 +324,8 @@ github.com/crewjam/saml v0.4.5/go.mod h1:qCJQpUtZte9R1ZjUBcW8qtCNlinbO363ooNl02S github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8 h1:PqOprF37OvwCbAN5W23znknGk6N/LMayqLAeP904FHE= github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva v1.17.1-0.20220105095955-fa1d1fc01d85 h1:4MjQ95MeeffQA9dCraON4YXBwkxVmJpxSNMKnn0ryZA= -github.com/cs3org/reva v1.17.1-0.20220105095955-fa1d1fc01d85/go.mod h1:WqO2/NkAmx1qes09G92lGPxxyroQgnZetJrCPItCcDo= +github.com/cs3org/reva v1.16.1-0.20220111150347-1b21aefbf8db h1:YCzbz8N0OHkO6AcA2SfXHCc02Y/DqSkO+hm8Pj+eDZ4= +github.com/cs3org/reva v1.16.1-0.20220111150347-1b21aefbf8db/go.mod h1:WqO2/NkAmx1qes09G92lGPxxyroQgnZetJrCPItCcDo= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -1277,8 +1278,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/studio-b12/gowebdav v0.0.0-20210917133250-a3a86976a1df/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s= -github.com/studio-b12/gowebdav v0.0.0-20211109083228-3f8721cd4b6f h1:L2NE7BXnSlSLoNYZ0lCwZDjdnYjCNYC71k9ClZUTFTs= -github.com/studio-b12/gowebdav v0.0.0-20211109083228-3f8721cd4b6f/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo= diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index 2809c146f4..12059dd0b7 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -15,8 +15,6 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" - v1beta11 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" ctxpkg "github.com/cs3org/reva/pkg/ctx" @@ -213,7 +211,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { return } - csr := provider.CreateStorageSpaceRequest{ + csr := storageprovider.CreateStorageSpaceRequest{ Owner: us, Type: driveType, Name: spaceName, @@ -226,7 +224,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { return } - if resp.GetStatus().GetCode() != v1beta11.Code_CODE_OK { + if resp.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "") return } @@ -266,32 +264,34 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) { return } + root := &storageprovider.ResourceId{} + identifierParts := strings.Split(driveID, "!") - if len(identifierParts) != 2 { + switch len(identifierParts) { + case 1: + root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[0] + case 2: + root.StorageId, root.OpaqueId = identifierParts[0], identifierParts[1] + default: errorcode.GeneralException.Render(w, r, http.StatusBadRequest, fmt.Sprintf("invalid resource id: %v", driveID)) w.WriteHeader(http.StatusInternalServerError) return } - storageID, opaqueID := identifierParts[0], identifierParts[1] - client, err := g.GetClient() if err != nil { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return } - updateSpaceRequest := &provider.UpdateStorageSpaceRequest{ + updateSpaceRequest := &storageprovider.UpdateStorageSpaceRequest{ // Prepare the object to apply the diff from. The properties on StorageSpace will overwrite // the original storage space. - StorageSpace: &provider.StorageSpace{ + StorageSpace: &storageprovider.StorageSpace{ Id: &storageprovider.StorageSpaceId{ - OpaqueId: driveID, - }, - Root: &provider.ResourceId{ - StorageId: storageID, - OpaqueId: opaqueID, + OpaqueId: root.StorageId + "!" + root.OpaqueId, }, + Root: root, }, } @@ -321,9 +321,9 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) { return } - if resp.GetStatus().GetCode() != v1beta11.Code_CODE_OK { + if resp.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { switch resp.Status.GetCode() { - case v1beta11.Code_CODE_NOT_FOUND: + case cs3rpc.Code_CODE_NOT_FOUND: errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, resp.GetStatus().GetMessage()) return default: @@ -395,17 +395,16 @@ func formatDriveItems(mds []*storageprovider.ResourceInfo) ([]*libregraph.DriveI func cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.StorageSpace) (*libregraph.Drive, error) { rootID := space.Root.StorageId + "!" + space.Root.OpaqueId + if space.Root.StorageId == space.Root.OpaqueId { + // omit opaqueid + rootID = space.Root.StorageId + } + drive := &libregraph.Drive{ - Id: &space.Id.OpaqueId, + Id: &rootID, Name: &space.Name, //"createdDateTime": "string (timestamp)", // TODO read from StorageSpace ... needs Opaque for now //"description": "string", // TODO read from StorageSpace ... needs Opaque for now - Owner: &libregraph.IdentitySet{ - User: &libregraph.Identity{ - Id: &space.Owner.Id.OpaqueId, - // DisplayName: , TODO read and cache from users provider - }, - }, DriveType: &space.SpaceType, Root: &libregraph.DriveItem{ Id: &rootID, @@ -420,6 +419,15 @@ func cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.StorageSpac drive.Root.WebDavUrl = &webDavURL } + // TODO The public space has no owner ... should we even show it? + if space.Owner != nil && space.Owner.Id != nil { + drive.Owner = &libregraph.IdentitySet{ + User: &libregraph.Identity{ + Id: &space.Owner.Id.OpaqueId, + // DisplayName: , TODO read and cache from users provider + }, + } + } if space.Mtime != nil { lastModified := cs3TimestampToTime(space.Mtime) drive.LastModifiedDateTime = &lastModified @@ -447,27 +455,26 @@ func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, mds []*storag if err != nil { return nil, err } - qta, err := g.getDriveQuota(ctx, mds[i]) + res.Quota, err = g.getDriveQuota(ctx, mds[i]) if err != nil { return nil, err } - res.Quota = &qta responses = append(responses, res) } return responses, nil } -func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.StorageSpace) (libregraph.Quota, error) { +func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.StorageSpace) (*libregraph.Quota, error) { client, err := g.GetClient() if err != nil { g.logger.Error().Err(err).Msg("error creating grpc client") - return libregraph.Quota{}, err + return nil, err } req := &gateway.GetQuotaRequest{ - Ref: &provider.Reference{ - ResourceId: &provider.ResourceId{ + Ref: &storageprovider.Reference{ + ResourceId: &storageprovider.ResourceId{ StorageId: space.Root.StorageId, OpaqueId: space.Root.OpaqueId, }, @@ -478,10 +485,13 @@ func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.Storage switch { case err != nil: g.logger.Error().Err(err).Msg("error sending get quota grpc request") - return libregraph.Quota{}, err + return nil, nil + case res.Status.Code == cs3rpc.Code_CODE_UNIMPLEMENTED: + // TODO well duh + return nil, nil case res.Status.Code != cs3rpc.Code_CODE_OK: g.logger.Error().Err(err).Msg("error sending sending get quota grpc request") - return libregraph.Quota{}, err + return nil, err } total := int64(res.TotalBytes) @@ -496,7 +506,7 @@ func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.Storage state := calculateQuotaState(total, used) qta.State = &state - return qta, nil + return &qta, nil } func calculateQuotaState(total int64, used int64) (state string) { @@ -514,16 +524,16 @@ func calculateQuotaState(total int64, used int64) (state string) { } } -func getQuota(quota *libregraph.Quota, defaultQuota string) *provider.Quota { +func getQuota(quota *libregraph.Quota, defaultQuota string) *storageprovider.Quota { switch { case quota != nil && quota.Total != nil: if q := *quota.Total; q >= 0 { - return &provider.Quota{QuotaMaxBytes: uint64(q)} + return &storageprovider.Quota{QuotaMaxBytes: uint64(q)} } fallthrough case defaultQuota != "": if q, err := strconv.ParseInt(defaultQuota, 10, 64); err == nil && q >= 0 { - return &provider.Quota{QuotaMaxBytes: uint64(q)} + return &storageprovider.Quota{QuotaMaxBytes: uint64(q)} } fallthrough default: diff --git a/ocis-pkg/indexer/index/cs3/autoincrement.go b/ocis-pkg/indexer/index/cs3/autoincrement.go index 1b223a7ed0..1c988e9768 100644 --- a/ocis-pkg/indexer/index/cs3/autoincrement.go +++ b/ocis-pkg/indexer/index/cs3/autoincrement.go @@ -19,6 +19,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/utils" "google.golang.org/grpc/metadata" "github.com/owncloud/ocis/ocis-pkg/indexer/index" @@ -93,6 +94,14 @@ func (idx *Autoincrement) Init() error { } idx.metadataStorage = &m + ctx, err := idx.getAuthenticatedContext(context.Background()) + if err != nil { + return err + } + if err := idx.metadataStorage.Init(ctx, idx.cs3conf.ServiceUser); err != nil { + return err + } + if err := idx.makeDirIfNotExists(idx.indexBaseDir); err != nil { return err } @@ -162,10 +171,14 @@ func (idx *Autoincrement) Remove(id string, v string) error { return err } - deletePath := path.Join("/meta", idx.indexRootDir, v) + deletePath := path.Join("/", idx.indexRootDir, v) resp, err := idx.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: deletePath, + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(deletePath), }, }) @@ -203,7 +216,11 @@ func (idx *Autoincrement) Search(pattern string) ([]string, error) { res, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", idx.indexRootDir), + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(idx.indexRootDir), }, }) @@ -289,8 +306,10 @@ func (idx *Autoincrement) makeDirIfNotExists(folder string) error { if err != nil { return err } - - return storage.MakeDirIfNotExist(ctx, idx.storageProvider, folder) + return storage.MakeDirIfNotExist(ctx, idx.storageProvider, &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, folder) } func (idx *Autoincrement) next() (int, error) { @@ -301,7 +320,11 @@ func (idx *Autoincrement) next() (int, error) { res, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", idx.indexRootDir), //TODO: + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(idx.indexRootDir), }, }) @@ -348,5 +371,5 @@ func (idx *Autoincrement) Delete() error { return err } - return deleteIndexRoot(ctx, idx.storageProvider, idx.indexRootDir) + return deleteIndexRoot(ctx, idx.storageProvider, idx.cs3conf.ServiceUser.UUID, idx.indexRootDir) } diff --git a/ocis-pkg/indexer/index/cs3/helper.go b/ocis-pkg/indexer/index/cs3/helper.go index 4cf5109d33..5024557e8c 100644 --- a/ocis-pkg/indexer/index/cs3/helper.go +++ b/ocis-pkg/indexer/index/cs3/helper.go @@ -3,16 +3,20 @@ package cs3 import ( "context" "fmt" - "path" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/pkg/utils" ) -func deleteIndexRoot(ctx context.Context, storageProvider provider.ProviderAPIClient, indexRootDir string) error { +func deleteIndexRoot(ctx context.Context, storageProvider provider.ProviderAPIClient, spaceid, indexRootDir string) error { res, err := storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", indexRootDir), + ResourceId: &provider.ResourceId{ + StorageId: spaceid, + OpaqueId: spaceid, + }, + Path: utils.MakeRelativePath(indexRootDir), }, }) if err != nil { diff --git a/ocis-pkg/indexer/index/cs3/non_unique.go b/ocis-pkg/indexer/index/cs3/non_unique.go index 8976199fc5..3e0f1a222d 100644 --- a/ocis-pkg/indexer/index/cs3/non_unique.go +++ b/ocis-pkg/indexer/index/cs3/non_unique.go @@ -15,6 +15,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/utils" idxerrs "github.com/owncloud/ocis/ocis-pkg/indexer/errors" "github.com/owncloud/ocis/ocis-pkg/indexer/index" "github.com/owncloud/ocis/ocis-pkg/indexer/option" @@ -95,6 +96,14 @@ func (idx *NonUnique) Init() error { } idx.metadataStorage = &m + ctx, err := idx.getAuthenticatedContext(context.Background()) + if err != nil { + return err + } + if err := idx.metadataStorage.Init(ctx, idx.cs3conf.ServiceUser); err != nil { + return err + } + if err := idx.makeDirIfNotExists(idx.indexBaseDir); err != nil { return err } @@ -119,7 +128,11 @@ func (idx *NonUnique) Lookup(v string) ([]string, error) { res, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", idx.indexRootDir, v), + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(path.Join("/", idx.indexRootDir, v)), }, }) @@ -172,10 +185,14 @@ func (idx *NonUnique) Remove(id string, v string) error { return err } - deletePath := path.Join("/meta", idx.indexRootDir, v, id) + deletePath := path.Join("/", idx.indexRootDir, v, id) resp, err := idx.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: deletePath, + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(deletePath), }, }) @@ -187,10 +204,14 @@ func (idx *NonUnique) Remove(id string, v string) error { return &idxerrs.NotFoundErr{TypeName: idx.typeName, Key: idx.indexBy, Value: v} } - toStat := path.Join("/meta", idx.indexRootDir, v) + toStat := path.Join("/", idx.indexRootDir, v) lcResp, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: toStat, + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(toStat), }, }) if err != nil { @@ -198,10 +219,14 @@ func (idx *NonUnique) Remove(id string, v string) error { } if len(lcResp.Infos) == 0 { - deletePath = path.Join("/meta", idx.indexRootDir, v) + deletePath = path.Join("/", idx.indexRootDir, v) _, err := idx.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: deletePath, + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(deletePath), }, }) if err != nil { @@ -245,7 +270,11 @@ func (idx *NonUnique) Search(pattern string) ([]string, error) { matches := make([]string, 0) res, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", idx.indexRootDir), + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(idx.indexRootDir), }, }) @@ -266,7 +295,11 @@ func (idx *NonUnique) Search(pattern string) ([]string, error) { for i := range foldersMatched { res, _ := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: foldersMatched[i], + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(foldersMatched[i]), }, }) @@ -303,7 +336,10 @@ func (idx *NonUnique) makeDirIfNotExists(folder string) error { if err != nil { return err } - return storage.MakeDirIfNotExist(ctx, idx.storageProvider, folder) + return storage.MakeDirIfNotExist(ctx, idx.storageProvider, &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, folder) } func (idx *NonUnique) createSymlink(oldname, newname string) error { @@ -356,5 +392,5 @@ func (idx *NonUnique) Delete() error { return err } - return deleteIndexRoot(ctx, idx.storageProvider, idx.indexRootDir) + return deleteIndexRoot(ctx, idx.storageProvider, idx.cs3conf.ServiceUser.UUID, idx.indexRootDir) } diff --git a/ocis-pkg/indexer/index/cs3/non_unique_test.go b/ocis-pkg/indexer/index/cs3/non_unique_test.go index c98a1574a1..3dd0527daf 100644 --- a/ocis-pkg/indexer/index/cs3/non_unique_test.go +++ b/ocis-pkg/indexer/index/cs3/non_unique_test.go @@ -32,7 +32,7 @@ package cs3 // sut := NewNonUniqueIndexWithOptions( // option.WithTypeName(GetTypeFQN(User{})), // option.WithIndexBy("UserName"), -// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/meta")), +// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/")), // option.WithDataDir(cfg.Repo.Disk.Path), // option.WithDataURL(cfg.Repo.CS3.DataURL), // option.WithDataPrefix(cfg.Repo.CS3.DataPrefix), diff --git a/ocis-pkg/indexer/index/cs3/unique.go b/ocis-pkg/indexer/index/cs3/unique.go index 7114d4fcf5..8bde7778f8 100644 --- a/ocis-pkg/indexer/index/cs3/unique.go +++ b/ocis-pkg/indexer/index/cs3/unique.go @@ -15,6 +15,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token" "github.com/cs3org/reva/pkg/token/manager/jwt" + "github.com/cs3org/reva/pkg/utils" idxerrs "github.com/owncloud/ocis/ocis-pkg/indexer/errors" "github.com/owncloud/ocis/ocis-pkg/indexer/index" "github.com/owncloud/ocis/ocis-pkg/indexer/option" @@ -90,6 +91,14 @@ func (idx *Unique) Init() error { } idx.metadataStorage = &m + ctx, err := idx.getAuthenticatedContext(context.Background()) + if err != nil { + return err + } + if err := idx.metadataStorage.Init(ctx, idx.cs3conf.ServiceUser); err != nil { + return err + } + if err := idx.makeDirIfNotExists(idx.indexBaseDir); err != nil { return err } @@ -162,10 +171,14 @@ func (idx *Unique) Remove(id string, v string) error { return err } - deletePath := path.Join("/meta", idx.indexRootDir, v) + deletePath := path.Join("/", idx.indexRootDir, v) resp, err := idx.storageProvider.Delete(ctx, &provider.DeleteRequest{ Ref: &provider.Reference{ - Path: deletePath, + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(deletePath), }, }) @@ -212,7 +225,11 @@ func (idx *Unique) Search(pattern string) ([]string, error) { res, err := idx.storageProvider.ListContainer(ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Path: path.Join("/meta", idx.indexRootDir), + ResourceId: &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, + Path: utils.MakeRelativePath(idx.indexRootDir), }, }) @@ -299,7 +316,10 @@ func (idx *Unique) makeDirIfNotExists(folder string) error { if err != nil { return err } - return storage.MakeDirIfNotExist(ctx, idx.storageProvider, folder) + return storage.MakeDirIfNotExist(ctx, idx.storageProvider, &provider.ResourceId{ + StorageId: idx.cs3conf.ServiceUser.UUID, + OpaqueId: idx.cs3conf.ServiceUser.UUID, + }, folder) } func (idx *Unique) getAuthenticatedContext(ctx context.Context) (context.Context, error) { @@ -318,5 +338,5 @@ func (idx *Unique) Delete() error { return err } - return deleteIndexRoot(ctx, idx.storageProvider, idx.indexRootDir) + return deleteIndexRoot(ctx, idx.storageProvider, idx.cs3conf.ServiceUser.UUID, idx.indexRootDir) } diff --git a/ocis-pkg/indexer/index/cs3/unique_test.go b/ocis-pkg/indexer/index/cs3/unique_test.go index a1a7edb7da..6c282e9085 100644 --- a/ocis-pkg/indexer/index/cs3/unique_test.go +++ b/ocis-pkg/indexer/index/cs3/unique_test.go @@ -32,7 +32,7 @@ package cs3 // sut := NewUniqueIndexWithOptions( // option.WithTypeName(GetTypeFQN(User{})), // option.WithIndexBy("UserName"), -// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/meta")), +// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/")), // option.WithDataDir(cfg.Repo.Disk.Path), // option.WithDataURL(cfg.Repo.CS3.DataURL), // option.WithDataPrefix(cfg.Repo.CS3.DataPrefix), @@ -82,7 +82,7 @@ package cs3 // sut := NewUniqueIndexWithOptions( // option.WithTypeName(GetTypeFQN(User{})), // option.WithIndexBy("UserName"), -// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/meta")), +// option.WithFilesDir(path.Join(cfg.Repo.Disk.Path, "/")), // option.WithDataDir(cfg.Repo.Disk.Path), // option.WithDataURL(cfg.Repo.CS3.DataURL), // option.WithDataPrefix(cfg.Repo.CS3.DataPrefix), diff --git a/ocis-pkg/metadata_storage/metadata_storage.go b/ocis-pkg/metadata_storage/metadata_storage.go index bb7527426a..51c293ec67 100644 --- a/ocis-pkg/metadata_storage/metadata_storage.go +++ b/ocis-pkg/metadata_storage/metadata_storage.go @@ -6,20 +6,20 @@ import ( "errors" "io/ioutil" "net/http" - "path" + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + v1beta11 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" revactx "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/utils" + "github.com/owncloud/ocis/accounts/pkg/config" "google.golang.org/grpc/metadata" ) -const ( - storageMountPath = "/meta" -) - func NewMetadataStorage(providerAddr string) (s MetadataStorage, err error) { - p, err := pool.GetStorageProviderServiceClient(providerAddr) if err != nil { return MetadataStorage{}, err @@ -36,17 +36,56 @@ func NewMetadataStorage(providerAddr string) (s MetadataStorage, err error) { type MetadataStorage struct { storageProvider provider.ProviderAPIClient dataGatewayClient *http.Client + SpaceRoot *provider.ResourceId } -func (r MetadataStorage) SimpleUpload(ctx context.Context, uploadpath string, content []byte) error { +// init creates the metadata space +func (ms *MetadataStorage) Init(ctx context.Context, serviceUser config.ServiceUser) (err error) { + // FIXME change CS3 api to allow sending a space id + cssr, err := ms.storageProvider.CreateStorageSpace(ctx, &provider.CreateStorageSpaceRequest{ + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "spaceid": { + Decoder: "plain", + Value: []byte(serviceUser.UUID), + }, + }, + }, + Owner: &user.User{ + Id: &user.UserId{ + OpaqueId: serviceUser.UUID, + }, + Groups: []string{}, + UidNumber: serviceUser.UID, + GidNumber: serviceUser.GID, + }, + Name: "Metadata", + Type: "metadata", + }) + switch { + case err != nil: + return err + case cssr.Status.Code == v1beta11.Code_CODE_OK: + ms.SpaceRoot = cssr.StorageSpace.Root + case cssr.Status.Code == v1beta11.Code_CODE_ALREADY_EXISTS: + // TODO make CreateStorageSpace return existing space? + ms.SpaceRoot = &provider.ResourceId{StorageId: serviceUser.UUID, OpaqueId: serviceUser.UUID} + default: + return errtypes.NewErrtypeFromStatus(cssr.Status) + } + return nil +} + +func (ms MetadataStorage) SimpleUpload(ctx context.Context, uploadpath string, content []byte) error { ref := provider.InitiateFileUploadRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, uploadpath), + ResourceId: ms.SpaceRoot, + Path: utils.MakeRelativePath(uploadpath), }, } - res, err := r.storageProvider.InitiateFileUpload(ctx, &ref) + res, err := ms.storageProvider.InitiateFileUpload(ctx, &ref) if err != nil { return err } @@ -70,7 +109,7 @@ func (r MetadataStorage) SimpleUpload(ctx context.Context, uploadpath string, co md, _ := metadata.FromOutgoingContext(ctx) req.Header.Add(revactx.TokenHeader, md.Get(revactx.TokenHeader)[0]) - resp, err := r.dataGatewayClient.Do(req) + resp, err := ms.dataGatewayClient.Do(req) if err != nil { return err } @@ -80,14 +119,15 @@ func (r MetadataStorage) SimpleUpload(ctx context.Context, uploadpath string, co return nil } -func (r MetadataStorage) SimpleDownload(ctx context.Context, downloadpath string) (content []byte, err error) { +func (ms MetadataStorage) SimpleDownload(ctx context.Context, downloadpath string) (content []byte, err error) { ref := provider.InitiateFileDownloadRequest{ Ref: &provider.Reference{ - Path: path.Join(storageMountPath, downloadpath), + ResourceId: ms.SpaceRoot, + Path: utils.MakeRelativePath(downloadpath), }, } - res, err := r.storageProvider.InitiateFileDownload(ctx, &ref) + res, err := ms.storageProvider.InitiateFileDownload(ctx, &ref) if err != nil { return []byte{}, err } @@ -95,13 +135,13 @@ func (r MetadataStorage) SimpleDownload(ctx context.Context, downloadpath string var endpoint string for _, proto := range res.GetProtocols() { - if proto.Protocol == "simple" { + if proto.Protocol == "spaces" { endpoint = proto.GetDownloadEndpoint() break } } if endpoint == "" { - return []byte{}, errors.New("metadata storage doesn't support the simple download protocol") + return []byte{}, errors.New("metadata storage doesn't support the spaces download protocol") } req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -111,7 +151,7 @@ func (r MetadataStorage) SimpleDownload(ctx context.Context, downloadpath string md, _ := metadata.FromOutgoingContext(ctx) req.Header.Add(revactx.TokenHeader, md.Get(revactx.TokenHeader)[0]) - resp, err := r.dataGatewayClient.Do(req) + resp, err := ms.dataGatewayClient.Do(req) if err != nil { return []byte{}, err } diff --git a/ocis/pkg/command/storagehome.go b/ocis/pkg/command/storageshares.go similarity index 54% rename from ocis/pkg/command/storagehome.go rename to ocis/pkg/command/storageshares.go index 14cf7ad912..1ae1c2a5e5 100644 --- a/ocis/pkg/command/storagehome.go +++ b/ocis/pkg/command/storageshares.go @@ -7,23 +7,22 @@ import ( "github.com/urfave/cli/v2" ) -// StorageHomeCommand is the entrypoint for the storage-home command. -func StorageHomeCommand(cfg *config.Config) *cli.Command { +// StorageSharesCommand is the entrypoint for the storage-shares command. +func StorageSharesCommand(cfg *config.Config) *cli.Command { return &cli.Command{ - Name: "storage-home", - Usage: "start storage and data provider for /home mount", + Name: "storage-shares", + Usage: "start storage and data provider for shares jail", Category: "extensions", - //Flags: flagset.StorageHomeWithConfig(cfg.Storage), Before: func(ctx *cli.Context) error { return ParseStorageCommon(ctx, cfg) }, Action: func(c *cli.Context) error { - origCmd := command.StorageHome(cfg.Storage) + origCmd := command.StorageShares(cfg.Storage) return handleOriginalAction(c, origCmd) }, } } func init() { - register.AddCommand(StorageHomeCommand) + register.AddCommand(StorageSharesCommand) } diff --git a/ocis/pkg/runtime/service/service.go b/ocis/pkg/runtime/service/service.go index 04f68d24b5..fa7c68586b 100644 --- a/ocis/pkg/runtime/service/service.go +++ b/ocis/pkg/runtime/service/service.go @@ -108,8 +108,8 @@ func NewService(options ...Option) (*Service, error) { s.ServicesRegistry["storage-authbasic"] = storage.NewAuthBasic s.ServicesRegistry["storage-authbearer"] = storage.NewAuthBearer s.ServicesRegistry["storage-authmachine"] = storage.NewAuthMachine - s.ServicesRegistry["storage-home"] = storage.NewStorageHome s.ServicesRegistry["storage-users"] = storage.NewStorageUsers + s.ServicesRegistry["storage-shares"] = storage.NewStorageShares s.ServicesRegistry["storage-public-link"] = storage.NewStoragePublicLink s.ServicesRegistry["storage-appprovider"] = storage.NewAppProvider diff --git a/ocs/pkg/server/http/svc_test.go b/ocs/pkg/server/http/svc_test.go index faffe9e461..b01095589c 100644 --- a/ocs/pkg/server/http/svc_test.go +++ b/ocs/pkg/server/http/svc_test.go @@ -480,6 +480,22 @@ func assertUsersSame(t *testing.T, expected, actual User, quotaAvailable bool) { } } +func findAccount(t *testing.T, username string) (*accountsProto.Account, error) { + cl := accountsProto.NewAccountsService("com.owncloud.api.accounts", service.Client()) + + req := &accountsProto.ListAccountsRequest{ + Query: "preferred_name eq '" + username + "'", + } + res, err := cl.ListAccounts(context.Background(), req) + if err != nil { + return nil, err + } + if len(res.Accounts) == 0 { + return nil, fmt.Errorf("username %s not found", username) + } + return res.Accounts[0], err +} + func deleteAccount(t *testing.T, id string) (*empty.Empty, error) { cl := accountsProto.NewAccountsService("com.owncloud.api.accounts", service.Client()) @@ -1431,12 +1447,17 @@ func TestGetSingleUser(t *testing.T) { t.Fatal(err) } + a, err := findAccount(t, user.ID) + if err != nil { + t.Fatal(err) + } + formatpart := getFormatString(format) res, err := sendRequest( "GET", fmt.Sprintf("/%v/cloud/user%v", ocsVersion, formatpart), "", - &User{ID: user.ID}, + &User{ID: a.Id}, []string{ssvc.BundleUUIDRoleUser}, ) diff --git a/ocs/pkg/service/v0/users.go b/ocs/pkg/service/v0/users.go index dd47b3d055..84cf9df2bd 100644 --- a/ocs/pkg/service/v0/users.go +++ b/ocs/pkg/service/v0/users.go @@ -19,6 +19,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/token/manager/jwt" "github.com/go-chi/chi/v5" + "github.com/google/uuid" accounts "github.com/owncloud/ocis/accounts/pkg/proto/v0" "github.com/owncloud/ocis/ocs/pkg/service/v0/data" "github.com/owncloud/ocis/ocs/pkg/service/v0/response" @@ -197,7 +198,7 @@ func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) { } newAccount := &accounts.Account{ - Id: userid, + Id: uuid.New().String(), DisplayName: displayname, PreferredName: userid, OnPremisesSamAccountName: userid, @@ -398,77 +399,51 @@ func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) { o.logger.Error().Err(err).Msg("error securing a connection to Reva gateway") } - homeResp, err := gwc.GetHome(ctx, &provider.GetHomeRequest{}) - if err != nil { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not get home").Error())) - return - } - - if homeResp.Status.Code != rpcv1beta1.Code_CODE_OK { - o.logger.Error(). - Str("stat_status_code", homeResp.Status.Code.String()). - Str("stat_message", homeResp.Status.Message). - Msg("DeleteUser: could not get user home: get failed") - return - } - - statResp, err := gwc.Stat(ctx, &provider.StatRequest{ - Ref: &provider.Reference{ - Path: homeResp.Path, + lsRes, err := gwc.ListStorageSpaces(ctx, &provider.ListStorageSpacesRequest{ + Filters: []*provider.ListStorageSpacesRequest_Filter{ + { + Type: provider.ListStorageSpacesRequest_Filter_TYPE_OWNER, + Term: &provider.ListStorageSpacesRequest_Filter_Owner{ + Owner: &revauser.UserId{ + Idp: o.config.IdentityManagement.Address, + OpaqueId: account.Id, + }, + }, + }, + { + Type: provider.ListStorageSpacesRequest_Filter_TYPE_SPACE_TYPE, + Term: &provider.ListStorageSpacesRequest_Filter_SpaceType{ + SpaceType: "personal", + }, + }, }, }) - if err != nil { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not stat home").Error())) + o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not list owned personal spaces").Error())) return } - if statResp.Status.Code != rpcv1beta1.Code_CODE_OK { + if lsRes.Status.Code != rpcv1beta1.Code_CODE_OK { o.logger.Error(). - Str("stat_status_code", statResp.Status.Code.String()). - Str("stat_message", statResp.Status.Message). - Msg("DeleteUser: could not delete user home: stat failed") + Interface("status", lsRes.Status). + Msg("DeleteUser: could not list personal spaces") return } - delReq := &provider.DeleteRequest{ - Ref: &provider.Reference{ - ResourceId: statResp.Info.Id, - }, - } - - delResp, err := gwc.Delete(ctx, delReq) - if err != nil { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not delete home").Error())) - return - } - - if delResp.Status.Code != rpcv1beta1.Code_CODE_OK { - o.logger.Error(). - Str("stat_status_code", statResp.Status.Code.String()). - Str("stat_message", statResp.Status.Message). - Msg("DeleteUser: could not delete user home: delete failed") - return - } - - req := &provider.PurgeRecycleRequest{ - Ref: &provider.Reference{ - Path: homeResp.Path, - }, - } - - purgeRecycleResponse, err := gwc.PurgeRecycle(ctx, req) - if err != nil { - o.mustRender(w, r, response.ErrRender(data.MetaServerError.StatusCode, errors.Wrap(err, "could not delete trash").Error())) - return - } - - if purgeRecycleResponse.Status.Code != rpcv1beta1.Code_CODE_OK { - o.logger.Error(). - Str("stat_status_code", statResp.Status.Code.String()). - Str("stat_message", statResp.Status.Message). - Msg("DeleteUser: could not delete user trash: delete failed") - return + for _, space := range lsRes.StorageSpaces { + dsRes, err := gwc.DeleteStorageSpace(ctx, &provider.DeleteStorageSpaceRequest{ + Id: space.Id, + }) + if err != nil { + o.logger.Error().Err(err).Msg("DeleteUser: could not make delete space request") + continue + } + if dsRes.Status.Code != rpcv1beta1.Code_CODE_OK && dsRes.Status.Code != rpcv1beta1.Code_CODE_NOT_FOUND { + o.logger.Error(). + Interface("status", dsRes.Status). + Msg("DeleteUser: could not delete space") + continue + } } } diff --git a/storage/pkg/command/frontend.go b/storage/pkg/command/frontend.go index 90b4827901..e96d2c1477 100644 --- a/storage/pkg/command/frontend.go +++ b/storage/pkg/command/frontend.go @@ -201,6 +201,7 @@ func frontendConfigFromStruct(c *cli.Context, cfg *config.Config, filesCfg map[s "resource_info_cache_ttl": cfg.Reva.Frontend.OCSResourceInfoCacheTTL, "prefix": cfg.Reva.Frontend.OCSPrefix, "additional_info_attribute": cfg.Reva.Frontend.OCSAdditionalInfoAttribute, + "machine_auth_apikey": cfg.Reva.AuthMachineConfig.MachineAuthAPIKey, "cache_warmup_driver": cfg.Reva.Frontend.OCSCacheWarmupDriver, "cache_warmup_drivers": map[string]interface{}{ "cbox": map[string]interface{}{ diff --git a/storage/pkg/command/gateway.go b/storage/pkg/command/gateway.go index 5570c959b9..0de42d2b91 100644 --- a/storage/pkg/command/gateway.go +++ b/storage/pkg/command/gateway.go @@ -179,9 +179,8 @@ func gatewayConfigFromStruct(c *cli.Context, cfg *config.Config, logger log.Logg "storageregistry": map[string]interface{}{ "driver": cfg.Reva.StorageRegistry.Driver, "drivers": map[string]interface{}{ - "static": map[string]interface{}{ - "home_provider": cfg.Reva.StorageRegistry.HomeProvider, - "rules": rules(cfg, logger), + "spaces": map[string]interface{}{ + "providers": spacesProviders(cfg, logger), }, }, }, @@ -191,7 +190,7 @@ func gatewayConfigFromStruct(c *cli.Context, cfg *config.Config, logger log.Logg return rcfg } -func rules(cfg *config.Config, logger log.Logger) map[string]map[string]interface{} { +func spacesProviders(cfg *config.Config, logger log.Logger) map[string]map[string]interface{} { // if a list of rules is given it overrides the generated rules from below if len(cfg.Reva.StorageRegistry.Rules) > 0 { @@ -219,18 +218,47 @@ func rules(cfg *config.Config, logger log.Logger) map[string]map[string]interfac } // generate rules based on default config - ret := map[string]map[string]interface{}{ - cfg.Reva.StorageHome.MountPath: {"address": cfg.Reva.StorageHome.Endpoint}, - cfg.Reva.StorageHome.AlternativeID: {"address": cfg.Reva.StorageHome.Endpoint}, - cfg.Reva.StorageUsers.MountPath: {"address": cfg.Reva.StorageUsers.Endpoint}, - cfg.Reva.StorageUsers.MountID + ".*": {"address": cfg.Reva.StorageUsers.Endpoint}, - cfg.Reva.StoragePublicLink.MountPath: {"address": cfg.Reva.StoragePublicLink.Endpoint}, - cfg.Reva.StoragePublicLink.MountID: {"address": cfg.Reva.StoragePublicLink.Endpoint}, + return map[string]map[string]interface{}{ + cfg.Reva.StorageUsers.Endpoint: { + "spaces": map[string]interface{}{ + "personal": map[string]interface{}{ + "mount_point": "/users", + "path_template": "/users/{{.Space.Owner.Id.OpaqueId}}", + }, + "project": map[string]interface{}{ + "mount_point": "/projects", + "path_template": "/projects/{{.Space.Name}}", + }, + }, + }, + cfg.Reva.StorageShares.Endpoint: { + "spaces": map[string]interface{}{ + "virtual": map[string]interface{}{ + // The root of the share jail is mounted here + "mount_point": "/users/{{.CurrentUser.Id.OpaqueId}}/Shares", + }, + "grant": map[string]interface{}{ + // Grants are relative to a space root that the gateway will determine with a stat + "mount_point": ".", + }, + "mountpoint": map[string]interface{}{ + // The jail needs to be filled with mount points + // .Space.Name is a path relative to the mount point + "mount_point": "/users/{{.CurrentUser.Id.OpaqueId}}/Shares", + "path_template": "/users/{{.CurrentUser.Id.OpaqueId}}/Shares/{{.Space.Name}}", + }, + }, + }, // public link storage returns the mount id of the actual storage + cfg.Reva.StoragePublicLink.Endpoint: { + "spaces": map[string]interface{}{ + "public": map[string]interface{}{ + "mount_point": "/public", + }, + }, + }, // medatada storage not part of the global namespace } - - return ret } func mimetypes(cfg *config.Config, logger log.Logger) []map[string]interface{} { diff --git a/storage/pkg/command/root.go b/storage/pkg/command/root.go index 477ec1df1a..29c5b6a384 100644 --- a/storage/pkg/command/root.go +++ b/storage/pkg/command/root.go @@ -21,9 +21,9 @@ func GetCommands(cfg *config.Config) cli.Commands { AuthBearer(cfg), AuthMachine(cfg), Sharing(cfg), - StorageHome(cfg), - StorageUsers(cfg), StoragePublicLink(cfg), + StorageShares(cfg), + StorageUsers(cfg), StorageMetadata(cfg), Health(cfg), } diff --git a/storage/pkg/command/storagedrivers/home.go b/storage/pkg/command/storagedrivers/home.go deleted file mode 100644 index 1f41bdb126..0000000000 --- a/storage/pkg/command/storagedrivers/home.go +++ /dev/null @@ -1,132 +0,0 @@ -package storagedrivers - -import ( - "github.com/owncloud/ocis/storage/pkg/config" -) - -func HomeDrivers(cfg *config.Config) map[string]interface{} { - return map[string]interface{}{ - "eos": map[string]interface{}{ - "namespace": cfg.Reva.UserStorage.EOS.Root, - "shadow_namespace": cfg.Reva.UserStorage.EOS.ShadowNamespace, - "uploads_namespace": cfg.Reva.UserStorage.EOS.UploadsNamespace, - "share_folder": cfg.Reva.UserStorage.EOS.ShareFolder, - "eos_binary": cfg.Reva.UserStorage.EOS.EosBinary, - "xrdcopy_binary": cfg.Reva.UserStorage.EOS.XrdcopyBinary, - "master_url": cfg.Reva.UserStorage.EOS.MasterURL, - "slave_url": cfg.Reva.UserStorage.EOS.SlaveURL, - "cache_directory": cfg.Reva.UserStorage.EOS.CacheDirectory, - "sec_protocol": cfg.Reva.UserStorage.EOS.SecProtocol, - "keytab": cfg.Reva.UserStorage.EOS.Keytab, - "single_username": cfg.Reva.UserStorage.EOS.SingleUsername, - "enable_logging": cfg.Reva.UserStorage.EOS.EnableLogging, - "show_hidden_sys_files": cfg.Reva.UserStorage.EOS.ShowHiddenSysFiles, - "force_single_user_mode": cfg.Reva.UserStorage.EOS.ForceSingleUserMode, - "use_keytab": cfg.Reva.UserStorage.EOS.UseKeytab, - "gatewaysvc": cfg.Reva.UserStorage.EOS.GatewaySVC, - }, - "eoshome": map[string]interface{}{ - "namespace": cfg.Reva.UserStorage.EOS.Root, - "shadow_namespace": cfg.Reva.UserStorage.EOS.ShadowNamespace, - "uploads_namespace": cfg.Reva.UserStorage.EOS.UploadsNamespace, - "share_folder": cfg.Reva.UserStorage.EOS.ShareFolder, - "eos_binary": cfg.Reva.UserStorage.EOS.EosBinary, - "xrdcopy_binary": cfg.Reva.UserStorage.EOS.XrdcopyBinary, - "master_url": cfg.Reva.UserStorage.EOS.MasterURL, - "slave_url": cfg.Reva.UserStorage.EOS.SlaveURL, - "cache_directory": cfg.Reva.UserStorage.EOS.CacheDirectory, - "sec_protocol": cfg.Reva.UserStorage.EOS.SecProtocol, - "keytab": cfg.Reva.UserStorage.EOS.Keytab, - "single_username": cfg.Reva.UserStorage.EOS.SingleUsername, - "user_layout": cfg.Reva.UserStorage.EOS.UserLayout, - "enable_logging": cfg.Reva.UserStorage.EOS.EnableLogging, - "show_hidden_sys_files": cfg.Reva.UserStorage.EOS.ShowHiddenSysFiles, - "force_single_user_mode": cfg.Reva.UserStorage.EOS.ForceSingleUserMode, - "use_keytab": cfg.Reva.UserStorage.EOS.UseKeytab, - "gatewaysvc": cfg.Reva.UserStorage.EOS.GatewaySVC, - }, - "eosgrpc": map[string]interface{}{ - "namespace": cfg.Reva.UserStorage.EOS.Root, - "shadow_namespace": cfg.Reva.UserStorage.EOS.ShadowNamespace, - "share_folder": cfg.Reva.UserStorage.EOS.ShareFolder, - "eos_binary": cfg.Reva.UserStorage.EOS.EosBinary, - "xrdcopy_binary": cfg.Reva.UserStorage.EOS.XrdcopyBinary, - "master_url": cfg.Reva.UserStorage.EOS.MasterURL, - "master_grpc_uri": cfg.Reva.UserStorage.EOS.GrpcURI, - "slave_url": cfg.Reva.UserStorage.EOS.SlaveURL, - "cache_directory": cfg.Reva.UserStorage.EOS.CacheDirectory, - "sec_protocol": cfg.Reva.UserStorage.EOS.SecProtocol, - "keytab": cfg.Reva.UserStorage.EOS.Keytab, - "single_username": cfg.Reva.UserStorage.EOS.SingleUsername, - "user_layout": cfg.Reva.UserStorage.EOS.UserLayout, - "enable_logging": cfg.Reva.UserStorage.EOS.EnableLogging, - "show_hidden_sys_files": cfg.Reva.UserStorage.EOS.ShowHiddenSysFiles, - "force_single_user_mode": cfg.Reva.UserStorage.EOS.ForceSingleUserMode, - "use_keytab": cfg.Reva.UserStorage.EOS.UseKeytab, - "enable_home": true, - "gatewaysvc": cfg.Reva.UserStorage.EOS.GatewaySVC, - }, - "local": map[string]interface{}{ - "root": cfg.Reva.UserStorage.Local.Root, - "share_folder": cfg.Reva.UserStorage.Local.ShareFolder, - }, - "localhome": map[string]interface{}{ - "root": cfg.Reva.UserStorage.Local.Root, - "share_folder": cfg.Reva.UserStorage.Local.ShareFolder, - "user_layout": cfg.Reva.UserStorage.Local.UserLayout, - }, - "owncloud": map[string]interface{}{ - "datadirectory": cfg.Reva.UserStorage.OwnCloud.Root, - "upload_info_dir": cfg.Reva.UserStorage.OwnCloud.UploadInfoDir, - "share_folder": cfg.Reva.UserStorage.OwnCloud.ShareFolder, - "user_layout": cfg.Reva.UserStorage.OwnCloud.UserLayout, - "redis": cfg.Reva.UserStorage.OwnCloud.Redis, - "enable_home": true, - "scan": cfg.Reva.UserStorage.OwnCloud.Scan, - "userprovidersvc": cfg.Reva.Users.Endpoint, - }, - "owncloudsql": map[string]interface{}{ - "datadirectory": cfg.Reva.UserStorage.OwnCloudSQL.Root, - "upload_info_dir": cfg.Reva.UserStorage.OwnCloudSQL.UploadInfoDir, - "share_folder": cfg.Reva.UserStorage.OwnCloudSQL.ShareFolder, - "user_layout": cfg.Reva.UserStorage.OwnCloudSQL.UserLayout, - "enable_home": true, - "dbusername": cfg.Reva.UserStorage.OwnCloudSQL.DBUsername, - "dbpassword": cfg.Reva.UserStorage.OwnCloudSQL.DBPassword, - "dbhost": cfg.Reva.UserStorage.OwnCloudSQL.DBHost, - "dbport": cfg.Reva.UserStorage.OwnCloudSQL.DBPort, - "dbname": cfg.Reva.UserStorage.OwnCloudSQL.DBName, - "userprovidersvc": cfg.Reva.Users.Endpoint, - }, - "ocis": map[string]interface{}{ - "root": cfg.Reva.UserStorage.OCIS.Root, - "enable_home": true, - "user_layout": cfg.Reva.UserStorage.OCIS.UserLayout, - "share_folder": cfg.Reva.UserStorage.OCIS.ShareFolder, - "treetime_accounting": true, - "treesize_accounting": true, - "owner": cfg.Reva.UserStorage.OCIS.ServiceUserUUID, // the accounts service system account uuid - }, - "s3": map[string]interface{}{ - "region": cfg.Reva.UserStorage.S3.Region, - "access_key": cfg.Reva.UserStorage.S3.AccessKey, - "secret_key": cfg.Reva.UserStorage.S3.SecretKey, - "endpoint": cfg.Reva.UserStorage.S3.Endpoint, - "bucket": cfg.Reva.UserStorage.S3.Bucket, - }, - "s3ng": map[string]interface{}{ - "root": cfg.Reva.UserStorage.S3NG.Root, - "enable_home": true, - "user_layout": cfg.Reva.UserStorage.S3NG.UserLayout, - "treetime_accounting": true, - "treesize_accounting": true, - "owner": cfg.Reva.UserStorage.S3NG.ServiceUserUUID, // the accounts service system account uuid - "share_folder": cfg.Reva.UserStorage.S3NG.ShareFolder, - "s3.region": cfg.Reva.UserStorage.S3NG.Region, - "s3.access_key": cfg.Reva.UserStorage.S3NG.AccessKey, - "s3.secret_key": cfg.Reva.UserStorage.S3NG.SecretKey, - "s3.endpoint": cfg.Reva.UserStorage.S3NG.Endpoint, - "s3.bucket": cfg.Reva.UserStorage.S3NG.Bucket, - }, - } -} diff --git a/storage/pkg/command/storagemetadata.go b/storage/pkg/command/storagemetadata.go index cb84b9ac8c..8ca9d41532 100644 --- a/storage/pkg/command/storagemetadata.go +++ b/storage/pkg/command/storagemetadata.go @@ -132,7 +132,6 @@ func storageMetadataFromStruct(c *cli.Context, cfg *config.Config) map[string]in }, "services": map[string]interface{}{ "storageprovider": map[string]interface{}{ - "mount_path": "/meta", "driver": cfg.Reva.StorageMetadata.Driver, "drivers": storagedrivers.MetadataDrivers(cfg), "data_server_url": cfg.Reva.StorageMetadata.DataServerURL, diff --git a/storage/pkg/command/storagepubliclink.go b/storage/pkg/command/storagepubliclink.go index 2615398134..ed2a239423 100644 --- a/storage/pkg/command/storagepubliclink.go +++ b/storage/pkg/command/storagepubliclink.go @@ -101,7 +101,6 @@ func storagePublicLinkConfigFromStruct(c *cli.Context, cfg *config.Config) map[s }, "services": map[string]interface{}{ "publicstorageprovider": map[string]interface{}{ - "mount_path": cfg.Reva.StoragePublicLink.MountPath, "mount_id": cfg.Reva.StoragePublicLink.MountID, "gateway_addr": cfg.Reva.Gateway.Endpoint, }, diff --git a/storage/pkg/command/storagehome.go b/storage/pkg/command/storageshares.go similarity index 50% rename from storage/pkg/command/storagehome.go rename to storage/pkg/command/storageshares.go index 8964e08872..ea0d0c9172 100644 --- a/storage/pkg/command/storagehome.go +++ b/storage/pkg/command/storageshares.go @@ -12,7 +12,6 @@ import ( "github.com/gofrs/uuid" "github.com/oklog/run" ociscfg "github.com/owncloud/ocis/ocis-pkg/config" - "github.com/owncloud/ocis/storage/pkg/command/storagedrivers" "github.com/owncloud/ocis/storage/pkg/config" "github.com/owncloud/ocis/storage/pkg/server/debug" "github.com/owncloud/ocis/storage/pkg/tracing" @@ -20,13 +19,13 @@ import ( "github.com/urfave/cli/v2" ) -// StorageHome is the entrypoint for the storage-home command. -func StorageHome(cfg *config.Config) *cli.Command { +// StorageShares is the entrypoint for the storage-shares command. +func StorageShares(cfg *config.Config) *cli.Command { return &cli.Command{ - Name: "storage-home", - Usage: "start storage-home service", + Name: "storage-shares", + Usage: "start storage-shares service", Before: func(c *cli.Context) error { - return ParseConfig(c, cfg, "storage-home") + return ParseConfig(c, cfg, "storage-shares") }, Action: func(c *cli.Context) error { logger := NewLogger(cfg) @@ -40,7 +39,7 @@ func StorageHome(cfg *config.Config) *cli.Command { uuid := uuid.Must(uuid.NewV4()) pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+uuid.String()+".pid") - rcfg := storageHomeConfigFromStruct(c, cfg) + rcfg := storageSharesConfigFromStruct(c, cfg) gr.Add(func() error { runtime.RunWithOptions( @@ -59,7 +58,7 @@ func StorageHome(cfg *config.Config) *cli.Command { debugServer, err := debug.Server( debug.Name(c.Command.Name+"-debug"), - debug.Addr(cfg.Reva.StorageHome.DebugAddr), + debug.Addr(cfg.Reva.StorageShares.DebugAddr), debug.Logger(logger), debug.Context(ctx), debug.Config(cfg), @@ -74,7 +73,7 @@ func StorageHome(cfg *config.Config) *cli.Command { cancel() }) - if !cfg.Reva.StorageHome.Supervised { + if !cfg.Reva.StorageShares.Supervised { sync.Trap(&gr, cancel) } @@ -83,11 +82,11 @@ func StorageHome(cfg *config.Config) *cli.Command { } } -// storageHomeConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service. -func storageHomeConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]interface{} { +// storageSharesConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service. +func storageSharesConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]interface{} { rcfg := map[string]interface{}{ "core": map[string]interface{}{ - "max_cpus": cfg.Reva.StorageHome.MaxCPUs, + "max_cpus": cfg.Reva.StorageShares.MaxCPUs, "tracing_enabled": cfg.Tracing.Enabled, "tracing_endpoint": cfg.Tracing.Endpoint, "tracing_collector": cfg.Tracing.Collector, @@ -99,38 +98,17 @@ func storageHomeConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] "skip_user_groups_in_token": cfg.Reva.SkipUserGroupsInToken, }, "grpc": map[string]interface{}{ - "network": cfg.Reva.StorageHome.GRPCNetwork, - "address": cfg.Reva.StorageHome.GRPCAddr, - // TODO build services dynamically + "network": cfg.Reva.StorageShares.GRPCNetwork, + "address": cfg.Reva.StorageShares.GRPCAddr, "services": map[string]interface{}{ - "storageprovider": map[string]interface{}{ - "driver": cfg.Reva.StorageHome.Driver, - "drivers": storagedrivers.HomeDrivers(cfg), - "mount_path": cfg.Reva.StorageHome.MountPath, - "mount_id": cfg.Reva.StorageHome.MountID, - "expose_data_server": cfg.Reva.StorageHome.ExposeDataServer, - "data_server_url": cfg.Reva.StorageHome.DataServerURL, - "tmp_folder": cfg.Reva.StorageHome.TempFolder, - }, - }, - }, - "http": map[string]interface{}{ - "network": cfg.Reva.StorageHome.HTTPNetwork, - "address": cfg.Reva.StorageHome.HTTPAddr, - // TODO build services dynamically - "services": map[string]interface{}{ - "dataprovider": map[string]interface{}{ - "prefix": cfg.Reva.StorageHome.HTTPPrefix, - "driver": cfg.Reva.StorageHome.Driver, - "drivers": storagedrivers.HomeDrivers(cfg), - "timeout": 86400, - "insecure": cfg.Reva.StorageHome.DataProvider.Insecure, - "disable_tus": false, + "sharesstorageprovider": map[string]interface{}{ + "usershareprovidersvc": cfg.Reva.Sharing.Endpoint, + "gateway_addr": cfg.Reva.Gateway.Endpoint, }, }, }, } - if cfg.Reva.StorageHome.ReadOnly { + if cfg.Reva.StorageShares.ReadOnly { gcfg := rcfg["grpc"].(map[string]interface{}) gcfg["interceptors"] = map[string]interface{}{ "readonly": map[string]interface{}{}, @@ -139,35 +117,35 @@ func storageHomeConfigFromStruct(c *cli.Context, cfg *config.Config) map[string] return rcfg } -// StorageHomeSutureService allows for the storage-home command to be embedded and supervised by a suture supervisor tree. -type StorageHomeSutureService struct { +// StorageSharesSutureService allows for the storage-shares command to be embedded and supervised by a suture supervisor tree. +type StorageSharesSutureService struct { cfg *config.Config } -// NewStorageHomeSutureService creates a new storage.StorageHomeSutureService -func NewStorageHome(cfg *ociscfg.Config) suture.Service { +// NewStorageShares creates a new storage.StorageSharesSutureService +func NewStorageShares(cfg *ociscfg.Config) suture.Service { cfg.Storage.Commons = cfg.Commons - return StorageHomeSutureService{ + return StorageSharesSutureService{ cfg: cfg.Storage, } } -func (s StorageHomeSutureService) Serve(ctx context.Context) error { - s.cfg.Reva.StorageHome.Context = ctx +func (s StorageSharesSutureService) Serve(ctx context.Context) error { + s.cfg.Reva.StorageShares.Context = ctx f := &flag.FlagSet{} - cmdFlags := StorageHome(s.cfg).Flags + cmdFlags := StorageShares(s.cfg).Flags for k := range cmdFlags { if err := cmdFlags[k].Apply(f); err != nil { return err } } cliCtx := cli.NewContext(nil, f, nil) - if StorageHome(s.cfg).Before != nil { - if err := StorageHome(s.cfg).Before(cliCtx); err != nil { + if StorageShares(s.cfg).Before != nil { + if err := StorageShares(s.cfg).Before(cliCtx); err != nil { return err } } - if err := StorageHome(s.cfg).Action(cliCtx); err != nil { + if err := StorageShares(s.cfg).Action(cliCtx); err != nil { return err } diff --git a/storage/pkg/command/storageusers.go b/storage/pkg/command/storageusers.go index 7a2be81e80..8aef59396e 100644 --- a/storage/pkg/command/storageusers.go +++ b/storage/pkg/command/storageusers.go @@ -106,7 +106,6 @@ func storageUsersConfigFromStruct(c *cli.Context, cfg *config.Config) map[string "storageprovider": map[string]interface{}{ "driver": cfg.Reva.StorageUsers.Driver, "drivers": storagedrivers.UserDrivers(cfg), - "mount_path": cfg.Reva.StorageUsers.MountPath, "mount_id": cfg.Reva.StorageUsers.MountID, "expose_data_server": cfg.Reva.StorageUsers.ExposeDataServer, "data_server_url": cfg.Reva.StorageUsers.DataServerURL, diff --git a/storage/pkg/config/config.go b/storage/pkg/config/config.go index ac042a47d4..6cd62c35d6 100644 --- a/storage/pkg/config/config.go +++ b/storage/pkg/config/config.go @@ -2,10 +2,6 @@ package config import ( "context" - "os" - "path" - - "github.com/owncloud/ocis/ocis-pkg/config/defaults" "github.com/owncloud/ocis/ocis-pkg/shared" ) @@ -195,7 +191,6 @@ type DataProvider struct { type StoragePort struct { Port Driver string `ocisConfig:"driver"` - MountPath string `ocisConfig:"mount_path"` MountID string `ocisConfig:"mount_id"` AlternativeID string `ocisConfig:"alternative_id"` ExposeDataServer bool `ocisConfig:"expose_data_server"` @@ -473,7 +468,7 @@ type Reva struct { AuthMachine Port `ocisConfig:"auth_machine"` AuthMachineConfig AuthMachineConfig `ocisConfig:"auth_machine_config"` Sharing Sharing `ocisConfig:"sharing"` - StorageHome StoragePort `ocisConfig:"storage_home"` + StorageShares StoragePort `ocisConfig:"storage_shares"` StorageUsers StoragePort `ocisConfig:"storage_users"` StoragePublicLink PublicStorage `ocisConfig:"storage_public_link"` StorageMetadata StoragePort `ocisConfig:"storage_metadata"` @@ -521,441 +516,6 @@ func New() *Config { return &Config{} } -func DefaultConfig() *Config { - return &Config{ - // log is inherited - Debug: Debug{ - Addr: "127.0.0.1:9109", - }, - Reva: Reva{ - JWTSecret: "Pive-Fumkiu4", - SkipUserGroupsInToken: false, - TransferSecret: "replace-me-with-a-transfer-secret", - TransferExpires: 24 * 60 * 60, - OIDC: OIDC{ - Issuer: "https://localhost:9200", - Insecure: false, - IDClaim: "preferred_username", - }, - LDAP: LDAP{ - Hostname: "localhost", - Port: 9126, - CACert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"), - Insecure: false, - BaseDN: "dc=ocis,dc=test", - LoginFilter: "(&(objectclass=posixAccount)(|(cn={{login}})(mail={{login}})))", - UserFilter: "(&(objectclass=posixAccount)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", - UserAttributeFilter: "(&(objectclass=posixAccount)({{attr}}={{value}}))", - UserFindFilter: "(&(objectclass=posixAccount)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", - UserGroupFilter: "(&(objectclass=posixGroup)(ownclouduuid={{.OpaqueId}}*))", - GroupFilter: "(&(objectclass=posixGroup)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", - GroupAttributeFilter: "(&(objectclass=posixGroup)({{attr}}={{value}}))", - GroupFindFilter: "(&(objectclass=posixGroup)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", - GroupMemberFilter: "(&(objectclass=posixAccount)(ownclouduuid={{.OpaqueId}}*))", - BindDN: "cn=reva,ou=sysusers,dc=ocis,dc=test", - BindPassword: "reva", - IDP: "https://localhost:9200", - UserSchema: LDAPUserSchema{ - UID: "ownclouduuid", - Mail: "mail", - DisplayName: "displayname", - CN: "cn", - UIDNumber: "uidnumber", - GIDNumber: "gidnumber", - }, - GroupSchema: LDAPGroupSchema{ - GID: "cn", - Mail: "mail", - DisplayName: "cn", - CN: "cn", - GIDNumber: "gidnumber", - }, - }, - UserGroupRest: UserGroupRest{ - RedisAddress: "localhost:6379", - }, - UserOwnCloudSQL: UserOwnCloudSQL{ - DBUsername: "owncloud", - DBPassword: "secret", - DBHost: "mysql", - DBPort: 3306, - DBName: "owncloud", - Idp: "https://localhost:9200", - Nobody: 90, - JoinUsername: false, - JoinOwnCloudUUID: false, - EnableMedialSearch: false, - }, - OCDav: OCDav{ - WebdavNamespace: "/home/", - DavFilesNamespace: "/users/", - }, - Archiver: Archiver{ - MaxNumFiles: 10000, - MaxSize: 1073741824, - ArchiverURL: "/archiver", - }, - UserStorage: StorageConfig{ - EOS: DriverEOS{ - DriverCommon: DriverCommon{ - Root: "/eos/dockertest/reva", - ShareFolder: "/Shares", - UserLayout: "{{substr 0 1 .Username}}/{{.Username}}", - }, - ShadowNamespace: "", // Defaults to path.Join(c.Namespace, ".shadow") - UploadsNamespace: "", // Defaults to path.Join(c.Namespace, ".uploads") - EosBinary: "/usr/bin/eos", - XrdcopyBinary: "/usr/bin/xrdcopy", - MasterURL: "root://eos-mgm1.eoscluster.cern.ch:1094", - SlaveURL: "root://eos-mgm1.eoscluster.cern.ch:1094", - CacheDirectory: os.TempDir(), - GatewaySVC: "127.0.0.1:9142", - }, - Local: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "local", "users"), - ShareFolder: "/Shares", - UserLayout: "{{.Username}}", - EnableHome: false, - }, - OwnCloud: DriverOwnCloud{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "owncloud"), - ShareFolder: "/Shares", - UserLayout: "{{.Id.OpaqueId}}", - EnableHome: false, - }, - UploadInfoDir: path.Join(defaults.BaseDataPath(), "storage", "uploadinfo"), - Redis: ":6379", - Scan: true, - }, - OwnCloudSQL: DriverOwnCloudSQL{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "owncloud"), - ShareFolder: "/Shares", - UserLayout: "{{.Username}}", - EnableHome: false, - }, - UploadInfoDir: path.Join(defaults.BaseDataPath(), "storage", "uploadinfo"), - DBUsername: "owncloud", - DBPassword: "owncloud", - DBHost: "", - DBPort: 3306, - DBName: "owncloud", - }, - S3: DriverS3{ - DriverCommon: DriverCommon{}, - Region: "default", - AccessKey: "", - SecretKey: "", - Endpoint: "", - Bucket: "", - }, - S3NG: DriverS3NG{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "users"), - ShareFolder: "/Shares", - UserLayout: "{{.Id.OpaqueId}}", - EnableHome: false, - }, - ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Region: "default", - AccessKey: "", - SecretKey: "", - Endpoint: "", - Bucket: "", - }, - OCIS: DriverOCIS{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "users"), - ShareFolder: "/Shares", - UserLayout: "{{.Id.OpaqueId}}", - }, - ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - }, - }, - MetadataStorage: StorageConfig{ - EOS: DriverEOS{ - DriverCommon: DriverCommon{ - Root: "/eos/dockertest/reva", - ShareFolder: "/Shares", - UserLayout: "{{substr 0 1 .Username}}/{{.Username}}", - EnableHome: false, - }, - ShadowNamespace: "", - UploadsNamespace: "", - EosBinary: "/usr/bin/eos", - XrdcopyBinary: "/usr/bin/xrdcopy", - MasterURL: "root://eos-mgm1.eoscluster.cern.ch:1094", - GrpcURI: "", - SlaveURL: "root://eos-mgm1.eoscluster.cern.ch:1094", - CacheDirectory: os.TempDir(), - EnableLogging: false, - ShowHiddenSysFiles: false, - ForceSingleUserMode: false, - UseKeytab: false, - SecProtocol: "", - Keytab: "", - SingleUsername: "", - GatewaySVC: "127.0.0.1:9142", - }, - Local: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "local", "metadata"), - }, - OwnCloud: DriverOwnCloud{}, - OwnCloudSQL: DriverOwnCloudSQL{}, - S3: DriverS3{ - DriverCommon: DriverCommon{}, - Region: "default", - }, - S3NG: DriverS3NG{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "metadata"), - ShareFolder: "", - UserLayout: "{{.Id.OpaqueId}}", - EnableHome: false, - }, - ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - Region: "default", - AccessKey: "", - SecretKey: "", - Endpoint: "", - Bucket: "", - }, - OCIS: DriverOCIS{ - DriverCommon: DriverCommon{ - Root: path.Join(defaults.BaseDataPath(), "storage", "metadata"), - ShareFolder: "", - UserLayout: "{{.Id.OpaqueId}}", - EnableHome: false, - }, - ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", - }, - }, - Frontend: FrontendPort{ - Port: Port{ - MaxCPUs: "", - LogLevel: "", - GRPCNetwork: "", - GRPCAddr: "", - HTTPNetwork: "tcp", - HTTPAddr: "127.0.0.1:9140", - Protocol: "", - Endpoint: "", - DebugAddr: "127.0.0.1:9141", - Services: []string{"datagateway", "ocdav", "ocs", "appprovider"}, - Config: nil, - Context: nil, - Supervised: false, - }, - AppProviderInsecure: false, - AppProviderPrefix: "", - ArchiverInsecure: false, - ArchiverPrefix: "archiver", - DatagatewayPrefix: "data", - Favorites: false, - OCDavInsecure: false, - OCDavPrefix: "", - OCSPrefix: "ocs", - OCSSharePrefix: "/Shares", - OCSHomeNamespace: "/home", - PublicURL: "https://localhost:9200", - OCSCacheWarmupDriver: "", - OCSAdditionalInfoAttribute: "{{.Mail}}", - OCSResourceInfoCacheTTL: 0, - Middleware: Middleware{}, - }, - DataGateway: DataGatewayPort{ - Port: Port{}, - PublicURL: "", - }, - Gateway: Gateway{ - Port: Port{ - Endpoint: "127.0.0.1:9142", - DebugAddr: "127.0.0.1:9143", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9142", - }, - CommitShareToStorageGrant: true, - CommitShareToStorageRef: true, - DisableHomeCreationOnLogin: false, - ShareFolder: "Shares", - LinkGrants: "", - HomeMapping: "", - EtagCacheTTL: 0, - }, - StorageRegistry: StorageRegistry{ - Driver: "static", - HomeProvider: "/home", - JSON: "", - }, - AppRegistry: AppRegistry{ - Driver: "static", - MimetypesJSON: "", - }, - Users: Users{ - Port: Port{ - Endpoint: "localhost:9144", - DebugAddr: "127.0.0.1:9145", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9144", - Services: []string{"userprovider"}, - }, - Driver: "ldap", - UserGroupsCacheExpiration: 5, - }, - Groups: Groups{ - Port: Port{ - Endpoint: "localhost:9160", - DebugAddr: "127.0.0.1:9161", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9160", - Services: []string{"groupprovider"}, - }, - Driver: "ldap", - GroupMembersCacheExpiration: 5, - }, - AuthProvider: Users{ - Port: Port{}, - Driver: "ldap", - UserGroupsCacheExpiration: 0, - }, - AuthBasic: Port{ - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9146", - DebugAddr: "127.0.0.1:9147", - Services: []string{"authprovider"}, - Endpoint: "localhost:9146", - }, - AuthBearer: Port{ - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9148", - DebugAddr: "127.0.0.1:9149", - Services: []string{"authprovider"}, - Endpoint: "localhost:9148", - }, - AuthMachine: Port{ - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9166", - DebugAddr: "127.0.0.1:9167", - Services: []string{"authprovider"}, - Endpoint: "localhost:9166", - }, - AuthMachineConfig: AuthMachineConfig{ - MachineAuthAPIKey: "change-me-please", - }, - Sharing: Sharing{ - Port: Port{ - Endpoint: "localhost:9150", - DebugAddr: "127.0.0.1:9151", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9150", - Services: []string{"usershareprovider", "publicshareprovider"}, - }, - UserDriver: "json", - UserJSONFile: path.Join(defaults.BaseDataPath(), "storage", "shares.json"), - UserSQLUsername: "", - UserSQLPassword: "", - UserSQLHost: "", - UserSQLPort: 1433, - UserSQLName: "", - PublicDriver: "json", - PublicJSONFile: path.Join(defaults.BaseDataPath(), "storage", "publicshares.json"), - PublicPasswordHashCost: 11, - PublicEnableExpiredSharesCleanup: true, - PublicJanitorRunInterval: 60, - UserStorageMountID: "", - }, - StorageHome: StoragePort{ - Port: Port{ - Endpoint: "localhost:9154", - DebugAddr: "127.0.0.1:9156", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9154", - HTTPNetwork: "tcp", - HTTPAddr: "127.0.0.1:9155", - }, - Driver: "ocis", - ReadOnly: false, - MountPath: "/home", - AlternativeID: "1284d238-aa92-42ce-bdc4-0b0000009154", - MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", - DataServerURL: "http://localhost:9155/data", - HTTPPrefix: "data", - TempFolder: path.Join(defaults.BaseDataPath(), "tmp", "home"), - }, - StorageUsers: StoragePort{ - Port: Port{ - Endpoint: "localhost:9157", - DebugAddr: "127.0.0.1:9159", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9157", - HTTPNetwork: "tcp", - HTTPAddr: "127.0.0.1:9158", - }, - MountPath: "/users", - MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", - Driver: "ocis", - DataServerURL: "http://localhost:9158/data", - HTTPPrefix: "data", - TempFolder: path.Join(defaults.BaseDataPath(), "tmp", "users"), - }, - StoragePublicLink: PublicStorage{ - StoragePort: StoragePort{ - Port: Port{ - Endpoint: "localhost:9178", - DebugAddr: "127.0.0.1:9179", - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9178", - }, - MountPath: "/public", - MountID: "e1a73ede-549b-4226-abdf-40e69ca8230d", - }, - PublicShareProviderAddr: "", - UserProviderAddr: "", - }, - StorageMetadata: StoragePort{ - Port: Port{ - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9215", - HTTPNetwork: "tcp", - HTTPAddr: "127.0.0.1:9216", - DebugAddr: "127.0.0.1:9217", - }, - Driver: "ocis", - ExposeDataServer: false, - DataServerURL: "http://localhost:9216/data", - TempFolder: path.Join(defaults.BaseDataPath(), "tmp", "metadata"), - DataProvider: DataProvider{}, - }, - AppProvider: AppProvider{ - Port: Port{ - GRPCNetwork: "tcp", - GRPCAddr: "127.0.0.1:9164", - DebugAddr: "127.0.0.1:9165", - Endpoint: "localhost:9164", - Services: []string{"appprovider"}, - }, - ExternalAddr: "127.0.0.1:9164", - WopiDriver: WopiDriver{}, - AppsURL: "/app/list", - OpenURL: "/app/open", - NewURL: "/app/new", - }, - Configs: nil, - UploadMaxChunkSize: 1e+8, - UploadHTTPMethodOverride: "", - ChecksumSupportedTypes: []string{"sha1", "md5", "adler32"}, - ChecksumPreferredUploadType: "", - DefaultUploadProtocol: "tus", - }, - Tracing: Tracing{ - Service: "storage", - Type: "jaeger", - }, - Asset: Asset{}, - } -} - // StructMappings binds a set of environment variables to a destination on cfg. Iterating over this set and editing the // Destination value of a binding will alter the original value, as it is a pointer to its memory address. This lets // us propagate changes easier. @@ -993,10 +553,6 @@ func structMappings(cfg *Config) []shared.EnvBinding { EnvVars: []string{"OCIS_INSECURE", "STORAGE_METADATA_DATAPROVIDER_INSECURE"}, Destination: &cfg.Reva.StorageMetadata.DataProvider.Insecure, }, - { - EnvVars: []string{"OCIS_INSECURE", "STORAGE_HOME_DATAPROVIDER_INSECURE"}, - Destination: &cfg.Reva.StorageHome.DataProvider.Insecure, - }, { EnvVars: []string{"OCIS_INSECURE", "STORAGE_FRONTEND_APPPROVIDER_INSECURE"}, Destination: &cfg.Reva.Frontend.AppProviderInsecure, @@ -1025,10 +581,6 @@ func structMappings(cfg *Config) []shared.EnvBinding { EnvVars: []string{"STORAGE_USERS_DRIVER"}, Destination: &cfg.Reva.StorageUsers.Driver, }, - { - EnvVars: []string{"STORAGE_HOME_DRIVER"}, - Destination: &cfg.Reva.StorageHome.Driver, - }, { EnvVars: []string{"STORAGE_USERS_DRIVER_OWNCLOUD_DATADIR"}, Destination: &cfg.Reva.UserStorage.OwnCloud.Root, @@ -1418,37 +970,21 @@ func structMappings(cfg *Config) []shared.EnvBinding { EnvVars: []string{"STORAGE_APPPROVIDER_ENDPOINT"}, Destination: &cfg.Reva.AppProvider.Endpoint, }, - { - EnvVars: []string{"STORAGE_HOME_ENDPOINT"}, - Destination: &cfg.Reva.StorageHome.Endpoint, - }, - { - EnvVars: []string{"STORAGE_HOME_MOUNT_PATH"}, - Destination: &cfg.Reva.StorageHome.MountPath, - }, - { - EnvVars: []string{"STORAGE_HOME_MOUNT_ID"}, - Destination: &cfg.Reva.StorageHome.MountID, - }, { EnvVars: []string{"STORAGE_USERS_ENDPOINT"}, Destination: &cfg.Reva.StorageUsers.Endpoint, }, - { - EnvVars: []string{"STORAGE_USERS_MOUNT_PATH"}, - Destination: &cfg.Reva.StorageUsers.MountPath, - }, { EnvVars: []string{"STORAGE_USERS_MOUNT_ID"}, Destination: &cfg.Reva.StorageUsers.MountID, }, { - EnvVars: []string{"STORAGE_PUBLIC_LINK_ENDPOINT"}, - Destination: &cfg.Reva.StoragePublicLink.Endpoint, + EnvVars: []string{"STORAGE_SHARES_ENDPOINT"}, + Destination: &cfg.Reva.StorageShares.Endpoint, }, { - EnvVars: []string{"STORAGE_PUBLIC_LINK_MOUNT_PATH"}, - Destination: &cfg.Reva.StoragePublicLink.MountPath, + EnvVars: []string{"STORAGE_PUBLIC_LINK_ENDPOINT"}, + Destination: &cfg.Reva.StoragePublicLink.Endpoint, }, // groups @@ -1695,48 +1231,6 @@ func structMappings(cfg *Config) []shared.EnvBinding { Destination: &cfg.Reva.Sharing.UserSQLName, }, - // storage home - { - EnvVars: []string{"STORAGE_HOME_DEBUG_ADDR"}, - Destination: &cfg.Reva.StorageHome.DebugAddr, - }, - { - EnvVars: []string{"STORAGE_HOME_GRPC_NETWORK"}, - Destination: &cfg.Reva.StorageHome.GRPCNetwork, - }, - { - EnvVars: []string{"STORAGE_HOME_GRPC_ADDR"}, - Destination: &cfg.Reva.StorageHome.GRPCAddr, - }, - { - EnvVars: []string{"STORAGE_HOME_HTTP_NETWORK"}, - Destination: &cfg.Reva.StorageHome.HTTPNetwork, - }, - { - EnvVars: []string{"STORAGE_HOME_HTTP_ADDR"}, - Destination: &cfg.Reva.StorageHome.HTTPAddr, - }, - { - EnvVars: []string{"OCIS_STORAGE_READ_ONLY", "STORAGE_HOME_READ_ONLY"}, - Destination: &cfg.Reva.StorageHome.ReadOnly, - }, - { - EnvVars: []string{"STORAGE_HOME_EXPOSE_DATA_SERVER"}, - Destination: &cfg.Reva.StorageHome.ExposeDataServer, - }, - { - EnvVars: []string{"STORAGE_HOME_DATA_SERVER_URL"}, - Destination: &cfg.Reva.StorageHome.DataServerURL, - }, - { - EnvVars: []string{"STORAGE_HOME_HTTP_PREFIX"}, - Destination: &cfg.Reva.StorageHome.HTTPPrefix, - }, - { - EnvVars: []string{"STORAGE_HOME_TMP_FOLDER"}, - Destination: &cfg.Reva.StorageHome.TempFolder, - }, - // storage metadata { EnvVars: []string{"STORAGE_METADATA_DEBUG_ADDR"}, @@ -1827,6 +1321,32 @@ func structMappings(cfg *Config) []shared.EnvBinding { Destination: &cfg.Reva.StorageUsers.TempFolder, }, + // storage shares + { + EnvVars: []string{"STORAGE_SHARES_DEBUG_ADDR"}, + Destination: &cfg.Reva.StorageShares.DebugAddr, + }, + { + EnvVars: []string{"STORAGE_SHARES_GRPC_NETWORK"}, + Destination: &cfg.Reva.StorageShares.GRPCNetwork, + }, + { + EnvVars: []string{"STORAGE_SHARES_GRPC_ADDR"}, + Destination: &cfg.Reva.StorageShares.GRPCAddr, + }, + { + EnvVars: []string{"STORAGE_SHARES_HTTP_NETWORK"}, + Destination: &cfg.Reva.StorageShares.HTTPNetwork, + }, + { + EnvVars: []string{"STORAGE_SHARES_HTTP_ADDR"}, + Destination: &cfg.Reva.StorageShares.HTTPAddr, + }, + { + EnvVars: []string{"OCIS_STORAGE_READ_ONLY", "STORAGE_SHARES_READ_ONLY"}, + Destination: &cfg.Reva.StorageShares.ReadOnly, + }, + // tracing { EnvVars: []string{"OCIS_TRACING_ENABLED", "STORAGE_TRACING_ENABLED"}, diff --git a/storage/pkg/config/defaultconfig.go b/storage/pkg/config/defaultconfig.go new file mode 100644 index 0000000000..0f266d4d65 --- /dev/null +++ b/storage/pkg/config/defaultconfig.go @@ -0,0 +1,436 @@ +package config + +import ( + "os" + "path" + + "github.com/owncloud/ocis/ocis-pkg/config/defaults" +) + +func DefaultConfig() *Config { + return &Config{ + // log is inherited + Debug: Debug{ + Addr: "127.0.0.1:9109", + }, + Reva: Reva{ + JWTSecret: "Pive-Fumkiu4", + SkipUserGroupsInToken: false, + TransferSecret: "replace-me-with-a-transfer-secret", + TransferExpires: 24 * 60 * 60, + OIDC: OIDC{ + Issuer: "https://localhost:9200", + Insecure: false, + IDClaim: "preferred_username", + }, + LDAP: LDAP{ + Hostname: "localhost", + Port: 9126, + CACert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"), + Insecure: false, + BaseDN: "dc=ocis,dc=test", + LoginFilter: "(&(objectclass=posixAccount)(|(cn={{login}})(mail={{login}})))", + UserFilter: "(&(objectclass=posixAccount)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", + UserAttributeFilter: "(&(objectclass=posixAccount)({{attr}}={{value}}))", + UserFindFilter: "(&(objectclass=posixAccount)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", + UserGroupFilter: "(&(objectclass=posixGroup)(cn={{.}}*))", // FIXME (&(objectclass=posixGroup)(ownclouduuid={{.OpaqueId}}*)) in reva the template is executed with a string. IIRC rhaferkamp mentioned this + GroupFilter: "(&(objectclass=posixGroup)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", + GroupAttributeFilter: "(&(objectclass=posixGroup)({{attr}}={{value}}))", + GroupFindFilter: "(&(objectclass=posixGroup)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", + GroupMemberFilter: "(&(objectclass=posixAccount)(ownclouduuid={{.OpaqueId}}*))", + BindDN: "cn=reva,ou=sysusers,dc=ocis,dc=test", + BindPassword: "reva", + IDP: "https://localhost:9200", + UserSchema: LDAPUserSchema{ + UID: "ownclouduuid", + Mail: "mail", + DisplayName: "displayname", + CN: "cn", + UIDNumber: "uidnumber", + GIDNumber: "gidnumber", + }, + GroupSchema: LDAPGroupSchema{ + GID: "cn", + Mail: "mail", + DisplayName: "cn", + CN: "cn", + GIDNumber: "gidnumber", + }, + }, + UserGroupRest: UserGroupRest{ + RedisAddress: "localhost:6379", + }, + UserOwnCloudSQL: UserOwnCloudSQL{ + DBUsername: "owncloud", + DBPassword: "secret", + DBHost: "mysql", + DBPort: 3306, + DBName: "owncloud", + Idp: "https://localhost:9200", + Nobody: 90, + JoinUsername: false, + JoinOwnCloudUUID: false, + EnableMedialSearch: false, + }, + OCDav: OCDav{ + WebdavNamespace: "/users/{{.Id.OpaqueId}}", + DavFilesNamespace: "/users/{{.Id.OpaqueId}}", + }, + Archiver: Archiver{ + MaxNumFiles: 10000, + MaxSize: 1073741824, + ArchiverURL: "/archiver", + }, + UserStorage: StorageConfig{ + EOS: DriverEOS{ + DriverCommon: DriverCommon{ + Root: "/eos/dockertest/reva", + ShareFolder: "/Shares", + UserLayout: "{{substr 0 1 .Username}}/{{.Username}}", + }, + ShadowNamespace: "", // Defaults to path.Join(c.Namespace, ".shadow") + UploadsNamespace: "", // Defaults to path.Join(c.Namespace, ".uploads") + EosBinary: "/usr/bin/eos", + XrdcopyBinary: "/usr/bin/xrdcopy", + MasterURL: "root://eos-mgm1.eoscluster.cern.ch:1094", + SlaveURL: "root://eos-mgm1.eoscluster.cern.ch:1094", + CacheDirectory: os.TempDir(), + GatewaySVC: "127.0.0.1:9142", + }, + Local: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "local", "users"), + ShareFolder: "/Shares", + UserLayout: "{{.Username}}", + EnableHome: false, + }, + OwnCloud: DriverOwnCloud{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "owncloud"), + ShareFolder: "/Shares", + UserLayout: "{{.Id.OpaqueId}}", + EnableHome: false, + }, + UploadInfoDir: path.Join(defaults.BaseDataPath(), "storage", "uploadinfo"), + Redis: ":6379", + Scan: true, + }, + OwnCloudSQL: DriverOwnCloudSQL{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "owncloud"), + ShareFolder: "/Shares", + UserLayout: "{{.Username}}", + EnableHome: false, + }, + UploadInfoDir: path.Join(defaults.BaseDataPath(), "storage", "uploadinfo"), + DBUsername: "owncloud", + DBPassword: "owncloud", + DBHost: "", + DBPort: 3306, + DBName: "owncloud", + }, + S3: DriverS3{ + DriverCommon: DriverCommon{}, + Region: "default", + AccessKey: "", + SecretKey: "", + Endpoint: "", + Bucket: "", + }, + S3NG: DriverS3NG{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "users"), + ShareFolder: "/Shares", + UserLayout: "{{.Id.OpaqueId}}", + EnableHome: false, + }, + ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + Region: "default", + AccessKey: "", + SecretKey: "", + Endpoint: "", + Bucket: "", + }, + OCIS: DriverOCIS{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "users"), + ShareFolder: "/Shares", + UserLayout: "{{.Id.OpaqueId}}", + }, + ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + }, + }, + MetadataStorage: StorageConfig{ + EOS: DriverEOS{ + DriverCommon: DriverCommon{ + Root: "/eos/dockertest/reva", + ShareFolder: "/Shares", + UserLayout: "{{substr 0 1 .Username}}/{{.Username}}", + EnableHome: false, + }, + ShadowNamespace: "", + UploadsNamespace: "", + EosBinary: "/usr/bin/eos", + XrdcopyBinary: "/usr/bin/xrdcopy", + MasterURL: "root://eos-mgm1.eoscluster.cern.ch:1094", + GrpcURI: "", + SlaveURL: "root://eos-mgm1.eoscluster.cern.ch:1094", + CacheDirectory: os.TempDir(), + EnableLogging: false, + ShowHiddenSysFiles: false, + ForceSingleUserMode: false, + UseKeytab: false, + SecProtocol: "", + Keytab: "", + SingleUsername: "", + GatewaySVC: "127.0.0.1:9142", + }, + Local: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "local", "metadata"), + }, + OwnCloud: DriverOwnCloud{}, + OwnCloudSQL: DriverOwnCloudSQL{}, + S3: DriverS3{ + DriverCommon: DriverCommon{}, + Region: "default", + }, + S3NG: DriverS3NG{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "metadata"), + ShareFolder: "", + UserLayout: "{{.Id.OpaqueId}}", + EnableHome: false, + }, + ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + Region: "default", + AccessKey: "", + SecretKey: "", + Endpoint: "", + Bucket: "", + }, + OCIS: DriverOCIS{ + DriverCommon: DriverCommon{ + Root: path.Join(defaults.BaseDataPath(), "storage", "metadata"), + ShareFolder: "", + UserLayout: "{{.Id.OpaqueId}}", + EnableHome: false, + }, + ServiceUserUUID: "95cb8724-03b2-11eb-a0a6-c33ef8ef53ad", + }, + }, + Frontend: FrontendPort{ + Port: Port{ + MaxCPUs: "", + LogLevel: "", + GRPCNetwork: "", + GRPCAddr: "", + HTTPNetwork: "tcp", + HTTPAddr: "127.0.0.1:9140", + Protocol: "", + Endpoint: "", + DebugAddr: "127.0.0.1:9141", + Services: []string{"datagateway", "ocdav", "ocs", "appprovider"}, + Config: nil, + Context: nil, + Supervised: false, + }, + AppProviderInsecure: false, + AppProviderPrefix: "", + ArchiverInsecure: false, + ArchiverPrefix: "archiver", + DatagatewayPrefix: "data", + Favorites: false, + OCDavInsecure: false, // true? + OCDavPrefix: "", + OCSPrefix: "ocs", + OCSSharePrefix: "/Shares", + OCSHomeNamespace: "/users/{{.Id.OpaqueId}}", + PublicURL: "https://localhost:9200", + OCSCacheWarmupDriver: "", + OCSAdditionalInfoAttribute: "{{.Mail}}", + OCSResourceInfoCacheTTL: 0, + Middleware: Middleware{}, + }, + DataGateway: DataGatewayPort{ + Port: Port{}, + PublicURL: "", + }, + Gateway: Gateway{ + Port: Port{ + Endpoint: "127.0.0.1:9142", + DebugAddr: "127.0.0.1:9143", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9142", + }, + CommitShareToStorageGrant: true, + CommitShareToStorageRef: true, + DisableHomeCreationOnLogin: false, + ShareFolder: "Shares", + LinkGrants: "", + HomeMapping: "", + EtagCacheTTL: 0, + }, + StorageRegistry: StorageRegistry{ + Driver: "spaces", + HomeProvider: "/home", // unused for spaces, static currently not supported + JSON: "", + }, + AppRegistry: AppRegistry{ + Driver: "static", + MimetypesJSON: "", + }, + Users: Users{ + Port: Port{ + Endpoint: "localhost:9144", + DebugAddr: "127.0.0.1:9145", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9144", + Services: []string{"userprovider"}, + }, + Driver: "ldap", + UserGroupsCacheExpiration: 5, + }, + Groups: Groups{ + Port: Port{ + Endpoint: "localhost:9160", + DebugAddr: "127.0.0.1:9161", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9160", + Services: []string{"groupprovider"}, + }, + Driver: "ldap", + GroupMembersCacheExpiration: 5, + }, + AuthProvider: Users{ + Port: Port{}, + Driver: "ldap", + UserGroupsCacheExpiration: 0, + }, + AuthBasic: Port{ + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9146", + DebugAddr: "127.0.0.1:9147", + Services: []string{"authprovider"}, + Endpoint: "localhost:9146", + }, + AuthBearer: Port{ + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9148", + DebugAddr: "127.0.0.1:9149", + Services: []string{"authprovider"}, + Endpoint: "localhost:9148", + }, + AuthMachine: Port{ + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9166", + DebugAddr: "127.0.0.1:9167", + Services: []string{"authprovider"}, + Endpoint: "localhost:9166", + }, + AuthMachineConfig: AuthMachineConfig{ + MachineAuthAPIKey: "change-me-please", + }, + Sharing: Sharing{ + Port: Port{ + Endpoint: "localhost:9150", + DebugAddr: "127.0.0.1:9151", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9150", + Services: []string{"usershareprovider", "publicshareprovider"}, + }, + UserDriver: "json", + UserJSONFile: path.Join(defaults.BaseDataPath(), "storage", "shares.json"), + UserSQLUsername: "", + UserSQLPassword: "", + UserSQLHost: "", + UserSQLPort: 1433, + UserSQLName: "", + PublicDriver: "json", + PublicJSONFile: path.Join(defaults.BaseDataPath(), "storage", "publicshares.json"), + PublicPasswordHashCost: 11, + PublicEnableExpiredSharesCleanup: true, + PublicJanitorRunInterval: 60, + UserStorageMountID: "", + }, + StorageShares: StoragePort{ + Port: Port{ + Endpoint: "localhost:9154", + DebugAddr: "127.0.0.1:9156", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9154", + HTTPNetwork: "tcp", + HTTPAddr: "127.0.0.1:9155", + }, + ReadOnly: false, + AlternativeID: "1284d238-aa92-42ce-bdc4-0b0000009154", + MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", + }, + StorageUsers: StoragePort{ + Port: Port{ + Endpoint: "localhost:9157", + DebugAddr: "127.0.0.1:9159", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9157", + HTTPNetwork: "tcp", + HTTPAddr: "127.0.0.1:9158", + }, + MountID: "1284d238-aa92-42ce-bdc4-0b0000009157", + Driver: "ocis", + DataServerURL: "http://localhost:9158/data", + HTTPPrefix: "data", + TempFolder: path.Join(defaults.BaseDataPath(), "tmp", "users"), + }, + StoragePublicLink: PublicStorage{ + StoragePort: StoragePort{ + Port: Port{ + Endpoint: "localhost:9178", + DebugAddr: "127.0.0.1:9179", + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9178", + }, + MountID: "7993447f-687f-490d-875c-ac95e89a62a4", + }, + PublicShareProviderAddr: "", + UserProviderAddr: "", + }, + StorageMetadata: StoragePort{ + Port: Port{ + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9215", + HTTPNetwork: "tcp", + HTTPAddr: "127.0.0.1:9216", + DebugAddr: "127.0.0.1:9217", + }, + Driver: "ocis", + ExposeDataServer: false, + DataServerURL: "http://localhost:9216/data", + TempFolder: path.Join(defaults.BaseDataPath(), "tmp", "metadata"), + DataProvider: DataProvider{}, + }, + AppProvider: AppProvider{ + Port: Port{ + GRPCNetwork: "tcp", + GRPCAddr: "127.0.0.1:9164", + DebugAddr: "127.0.0.1:9165", + Endpoint: "localhost:9164", + Services: []string{"appprovider"}, + }, + ExternalAddr: "127.0.0.1:9164", + WopiDriver: WopiDriver{}, + AppsURL: "/app/list", + OpenURL: "/app/open", + NewURL: "/app/new", + }, + Configs: nil, + UploadMaxChunkSize: 1e+8, + UploadHTTPMethodOverride: "", + ChecksumSupportedTypes: []string{"sha1", "md5", "adler32"}, + ChecksumPreferredUploadType: "", + DefaultUploadProtocol: "tus", + }, + Tracing: Tracing{ + Service: "storage", + Type: "jaeger", + }, + Asset: Asset{}, + } +} diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index 4cf034f92d..f566358786 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -341,21 +341,14 @@ File and sync features in a shared scenario - [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:48](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L48) #### [Shares received in different ways are not merged](https://github.com/owncloud/ocis/issues/2711) -- [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:553](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L553) -- [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:554](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L554) - [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:598](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L598) - [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:599](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L599) - [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:621](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L621) - [apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature:622](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareCreateSpecialToShares1/createShareReceivedInMultipleWays.feature#L622) #### [file_target of a auto-renamed file is not correct directly after sharing](https://github.com/owncloud/core/issues/32322) -- [apiShareManagementBasicToShares/deleteShareFromShares.feature:59](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/deleteShareFromShares.feature#L59) - [apiShareManagementToShares/mergeShare.feature:89](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/mergeShare.feature#L89) -#### [Listing shares via ocs API does not show path for parent folders](https://github.com/owncloud/ocis/issues/1231) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:290](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L290) -- [apiShareManagementBasicToShares/createShareToSharesFolder.feature:291](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L291) - #### [Cannot move a file to a shared folder](https://github.com/owncloud/ocis/issues/2146) - [apiShareManagementBasicToShares/createShareToSharesFolder.feature:509](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L515) @@ -417,18 +410,6 @@ cannot share a folder with create permission - [apiSharePublicLink1/changingPublicLinkShare.feature:51](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/changingPublicLinkShare.feature#L51) - [apiSharePublicLink1/changingPublicLinkShare.feature:90](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/changingPublicLinkShare.feature#L90) -#### [Public link enforce permissions](https://github.com/owncloud/ocis/issues/1269) - -- [apiSharePublicLink1/createPublicLinkShare.feature:141](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L141) -- [apiSharePublicLink1/createPublicLinkShare.feature:142](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L142) -- [apiSharePublicLink1/createPublicLinkShare.feature:218](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L218) -- [apiSharePublicLink1/createPublicLinkShare.feature:219](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L219) - -#### [Ability to return error messages in Webdav response bodies](https://github.com/owncloud/ocis/issues/1293) - -- [apiSharePublicLink1/createPublicLinkShare.feature:105](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L105) -- [apiSharePublicLink1/createPublicLinkShare.feature:106](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L106) - #### [various sharing settings cannot be set](https://github.com/owncloud/ocis/issues/1328) - [apiSharePublicLink1/createPublicLinkShare.feature:319](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink1/createPublicLinkShare.feature#L319) @@ -600,11 +581,6 @@ _getting and setting quota_ - [apiWebdavProperties1/getQuota.feature:27](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L27) - [apiWebdavProperties1/getQuota.feature:28](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties1/getQuota.feature#L28) - -#### [cannot get share-types webdav property](https://github.com/owncloud/ocis/issues/567) -- [apiWebdavProperties2/getFileProperties.feature:174](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L174) -- [apiWebdavProperties2/getFileProperties.feature:175](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L175) - #### [Private link support](https://github.com/owncloud/product/issues/201) #### [oc:privatelink property not returned in webdav responses](https://github.com/owncloud/product/issues/262) - [apiWebdavProperties2/getFileProperties.feature:232](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavProperties2/getFileProperties.feature#L232) @@ -657,12 +633,9 @@ Scenario Outline: Moving a file into a shared folder as the sharee and as the sh - [apiWebdavMove2/moveFile.feature:290](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavMove2/moveFile.feature#L290) - [apiWebdavMove2/moveFile.feature:291](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavMove2/moveFile.feature#L291) -#### [User loses accepted share if owner changes the contents of the file](https://github.com/owncloud/ocis/issues/2706) -- [apiVersions/fileVersionsSharingToShares.feature:32](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature#L32) - #### [restoring an older version of a shared file deletes the share](https://github.com/owncloud/ocis/issues/765) - [apiShareManagementToShares/acceptShares.feature:587](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/acceptShares.feature#L587) -- [apiVersions/fileVersionsSharingToShares.feature:43](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature#L43) + #### [not possible to move file into a received folder](https://github.com/owncloud/ocis/issues/764) - [apiVersions/fileVersionsSharingToShares.feature:219](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature#L219) @@ -866,9 +839,6 @@ _ocs: api compatibility, return correct status code_ - [apiShareManagementBasicToShares/createShareToSharesFolder.feature:670](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L670) - [apiShareManagementBasicToShares/createShareToSharesFolder.feature:671](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/createShareToSharesFolder.feature#L671) -#### [OCIS-storage overwriting a file as share receiver, does not create a new file version for the sharer](https://github.com/owncloud/ocis/issues/766) -- [apiVersions/fileVersionsSharingToShares.feature:294](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiVersions/fileVersionsSharingToShares.feature#L294) - #### [deleting a share with wrong authentication returns OCS status 996 / HTTP 500](https://github.com/owncloud/ocis/issues/1229) - [apiShareManagementBasicToShares/deleteShareFromShares.feature:250](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/deleteShareFromShares.feature#L250) - [apiShareManagementBasicToShares/deleteShareFromShares.feature:251](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementBasicToShares/deleteShareFromShares.feature#L251) @@ -1066,9 +1036,6 @@ API, search, favorites, config, capabilities, not existing endpoints, CORS and o #### [Trying to access another user's file gives http 403 instead of 404](https://github.com/owncloud/ocis/issues/2175) _ocdav: api compatibility, return correct status code_ -- [apiAuthWebDav/webDavDELETEAuth.feature:38](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavDELETEAuth.feature#L38) Scenario: send DELETE requests to another user's webDav endpoints as normal user -- [apiAuthWebDav/webDavPROPFINDAuth.feature:39](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPROPFINDAuth.feature#L39) Scenario: send PROPFIND requests to another user's webDav endpoints as normal user -- [apiAuthWebDav/webDavPROPPATCHAuth.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPROPPATCHAuth.feature#L40) Scenario: send PROPPATCH requests to another user's webDav endpoints as normal user - [apiAuthWebDav/webDavMKCOLAuth.feature:36](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavMKCOLAuth.feature#L36) Scenario: send MKCOL requests to another user's webDav endpoints as normal user #### [trying to lock file of another user gives http 200](https://github.com/owncloud/ocis/issues/2176) @@ -1082,6 +1049,9 @@ _ocdav: api compatibility, return correct status code_ _ocdav: api compatibility, return correct status code_ - [apiAuthWebDav/webDavPOSTAuth.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPOSTAuth.feature#L40) Scenario: send POST requests to another user's webDav endpoints as normal user +#### Another users space literally does not exist because it is not listed as a space for him, 404 seems correct, expects 403 +- [apiAuthWebDav/webDavPUTAuth.feature:40](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavPUTAuth.feature#L40) + #### [Using double slash in URL to access a folder gives 501 and other status codes](https://github.com/owncloud/ocis/issues/1667) - [apiAuthWebDav/webDavSpecialURLs.feature:13](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavSpecialURLs.feature#L13) - [apiAuthWebDav/webDavSpecialURLs.feature:24](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiAuthWebDav/webDavSpecialURLs.feature#L24) @@ -1138,12 +1108,6 @@ And other missing implementation of favorites - [apiFavorites/favorites.feature:149](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L149) - [apiFavorites/favorites.feature:176](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L176) - [apiFavorites/favorites.feature:177](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favorites.feature#L177) -- [apiFavorites/favoritesSharingToShares.feature:21](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L21) -- [apiFavorites/favoritesSharingToShares.feature:22](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L22) -- [apiFavorites/favoritesSharingToShares.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L35) -- [apiFavorites/favoritesSharingToShares.feature:36](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L36) -- [apiFavorites/favoritesSharingToShares.feature:48](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L48) -- [apiFavorites/favoritesSharingToShares.feature:49](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L49) - [apiFavorites/favoritesSharingToShares.feature:62](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L62) - [apiFavorites/favoritesSharingToShares.feature:63](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiFavorites/favoritesSharingToShares.feature#L63) @@ -1351,10 +1315,6 @@ Scenario Outline: Unauthenticated call #### [Share inaccessible if folder with same name was deleted and recreated](https://github.com/owncloud/ocis/issues/1787) - [apiShareReshareToShares1/reShare.feature:269](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L269) - [apiShareReshareToShares1/reShare.feature:270](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L270) -- [apiShareReshareToShares1/reShare.feature:287](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L287) -- [apiShareReshareToShares1/reShare.feature:288](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L288) -- [apiShareReshareToShares1/reShare.feature:305](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L305) -- [apiShareReshareToShares1/reShare.feature:306](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareReshareToShares1/reShare.feature#L306) #### [Trying to accept a share with invalid ID gives incorrect OCS and HTTP status](https://github.com/owncloud/ocis/issues/2111) - [apiShareOperationsToShares2/shareAccessByID.feature:85](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/shareAccessByID.feature#L85) @@ -1461,22 +1421,18 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers - [apiWebdavUpload1/uploadFileToBlacklistedName.feature:66](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFileToBlacklistedName.feature#L66) - [apiWebdavUpload1/uploadFileToBlacklistedName.feature:67](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavUpload1/uploadFileToBlacklistedName.feature#L67) -### [not possible to overwrite a received shared file](https://github.com/owncloud/ocis/issues/2267) -- [apiShareOperationsToShares1/changingFilesShare.feature:114](https://github.com/owncloud/web/blob/master/tests/acceptance/features/apiShareOperationsToShares1/changingFilesShare.feature#L114) - -### [Allow public link sharing only for certain groups feature not implemented] +#### [Allow public link sharing only for certain groups feature not implemented] - [apiSharePublicLink2/allowGroupToCreatePublicLinks.feature:35](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/allowGroupToCreatePublicLinks.feature#L35) - [apiSharePublicLink2/allowGroupToCreatePublicLinks.feature:91](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiSharePublicLink2/allowGroupToCreatePublicLinks.feature#L91) -### [Cannot download preview of shared received file after the shareowner has changed the file content](https://github.com/owncloud/ocis/issues/2538) -- [apiWebdavPreviews/previews.feature:196](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L196) +#### [Cannot download preview of shared received file after the shareowner has changed the file content](https://github.com/owncloud/ocis/issues/2538) - [apiWebdavPreviews/previews.feature:217](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L217) - [apiWebdavPreviews/previews.feature:233](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L233) -### [Preview of text file with UTF content does not render correctly](https://github.com/owncloud/ocis/issues/2570) +#### [Preview of text file with UTF content does not render correctly](https://github.com/owncloud/ocis/issues/2570) - [apiWebdavPreviews/previews.feature:208](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavPreviews/previews.feature#L208) -### [Share path in the response is different between share states](https://github.com/owncloud/ocis/issues/2540) +#### [Share path in the response is different between share states](https://github.com/owncloud/ocis/issues/2540) - [apiShareManagementToShares/acceptShares.feature:65](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/acceptShares.feature#L65) - [apiShareManagementToShares/acceptShares.feature:93](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/acceptShares.feature#L93) - [apiShareManagementToShares/acceptShares.feature:228](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareManagementToShares/acceptShares.feature#L228) @@ -1488,6 +1444,6 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers - [apiShareOperationsToShares2/shareAccessByID.feature:124](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/shareAccessByID.feature#L124) - [apiShareOperationsToShares2/shareAccessByID.feature:125](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiShareOperationsToShares2/shareAccessByID.feature#L125) -### [Content-type is not multipart/byteranges when downloading file with Range Header](https://github.com/owncloud/ocis/issues/2677) +#### [Content-type is not multipart/byteranges when downloading file with Range Header](https://github.com/owncloud/ocis/issues/2677) - [apiWebdavOperations/downloadFile.feature:169](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L169) - [apiWebdavOperations/downloadFile.feature:170](https://github.com/owncloud/core/blob/master/tests/acceptance/features/apiWebdavOperations/downloadFile.feature#L170) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index e7f8deb044..591c12dcf5 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -1,14 +1,23 @@ ## Scenarios from OCIS API tests that are expected to fail with OCIS storage -#### [downloading the /Shares folder using the archiver endpoint does not work](https://github.com/owncloud/ocis/issues/2751) -- [apiArchiver/downloadById.feature:134](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L134) -- [apiArchiver/downloadById.feature:135](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L135) - #### [downloading an archive with invalid path returns HTTP/500](https://github.com/owncloud/ocis/issues/2768) -- [apiArchiver/downloadByPath.feature:69](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/apiArchiver/downloadByPath.feature#L69) +- [apiArchiver/downloadByPath.feature:69] -#### [downloading an archive with non existing / accessible id returns HTTP/500](https://github.com/owncloud/ocis/issues/2795) -- [apiArchiver/downloadById.feature:69](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L69) +#### [Hardcoded call to /home/..., but /home no longer exists](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/apiArchiver/downloadByPath.feature#L26) +- [apiArchiver/downloadByPath.feature:26](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L26) +- [apiArchiver/downloadByPath.feature:27](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L27) +- [apiArchiver/downloadByPath.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L44) +- [apiArchiver/downloadByPath.feature:45](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L45) +- [apiArchiver/downloadByPath.feature:48](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L48) +- [apiArchiver/downloadByPath.feature:69](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L69) +- [apiArchiver/downloadByPath.feature:74](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L74) +- [apiArchiver/downloadByPath.feature:132](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L132) +- [apiArchiver/downloadByPath.feature:133](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiArchiver/downloadByPath.feature#L133) + +### Tries to download /Shares/ folder but it cannot be downloaded any more directly +- [apiArchiver/downloadById.feature:134](https://github.com/owncloud/web/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L134) +- [apiArchiver/downloadById.feature:135](https://github.com/owncloud/web/blob/master/tests/acceptance/features/apiArchiver/downloadById.feature#L135) #### [Overwriting a file in the space within the allowed quota does not work](https://github.com/owncloud/ocis/issues/2829) - [apiSpaces/quota.feature:56](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpaces/quota.feature#L56) + diff --git a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md index 657b0b7d9e..fb3233908f 100644 --- a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md @@ -122,8 +122,6 @@ Other free text and markdown formatting can be used elsewhere in the document if - [webUIRestrictSharing/restrictSharing.feature:56](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIRestrictSharing/restrictSharing.feature#L56) ### [First request with a recreated user returns a 401 error](https://github.com/owncloud/ocis/issues/1675) -- [webUISharingAutocompletion/shareAutocompletion.feature:56](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L56) -- [webUISharingAutocompletion/shareAutocompletion.feature:66](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L66) - [webUISharingAutocompletion/shareAutocompletion.feature:128](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L128) - [webUISharingAutocompletion/shareAutocompletion.feature:141](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAutocompletion/shareAutocompletion.feature#L141) @@ -510,3 +508,13 @@ Other free text and markdown formatting can be used elsewhere in the document if ### [shares are not listed with full paths](https://github.com/owncloud/ocis/issues/2462) - [webUISharingPublicBasic/publicLinkCreate.feature:88](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingPublicBasic/publicLinkCreate.feature#L88) + +### Shares folder cannot be deleted and is always visible +- [webUIDeleteFilesFolders/deleteFilesFolders.feature:77](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIDeleteFilesFolders/deleteFilesFolders.feature#L77) +- [webUIDeleteFilesFolders/deleteFilesFolders.feature:89](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIDeleteFilesFolders/deleteFilesFolders.feature#L89) +- [webUISharingAcceptShares/acceptShares.feature:72](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingAcceptShares/acceptShares.feature#L72) +- [webUIOperationsWithFolderShares/accessToSharesFolder.feature:14](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIOperationsWithFolderShares/accessToSharesFolder.feature#L14) + +### [web config update is not properly reflected after the ocis start](https://github.com/owncloud/ocis/issues/2944) +- [webUIFiles/breadcrumb.feature:50](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUIFiles/breadcrumb.feature#L50) + diff --git a/tests/acceptance/features/apiArchiver/downloadById.feature b/tests/acceptance/features/apiArchiver/downloadById.feature index 1437a97639..fef3847928 100644 --- a/tests/acceptance/features/apiArchiver/downloadById.feature +++ b/tests/acceptance/features/apiArchiver/downloadById.feature @@ -70,7 +70,7 @@ Feature: download multiple resources bundled into an archive Given user "Brian" has been created with default attributes and without skeleton files And user "Alice" has uploaded file with content "some data" to "/textfile0.txt" When user "Brian" downloads the archive of "/textfile0.txt" of user "Alice" using the resource id - Then the HTTP status code should be "400" + Then the HTTP status code should be "404" Scenario: download multiple shared items as share receiver diff --git a/tests/acceptance/features/apiSpaces/shareSpaces.feature b/tests/acceptance/features/apiSpaces/shareSpaces.feature index c65eac05d9..3d4dd7b693 100644 --- a/tests/acceptance/features/apiSpaces/shareSpaces.feature +++ b/tests/acceptance/features/apiSpaces/shareSpaces.feature @@ -26,7 +26,7 @@ Feature: Share spaces When user "Brian" lists all available spaces via the GraphApi Then the json responded should contain a space "Share space to Brian" with these key and value pairs: | key | value | - | driveType | share | + | driveType | project | | id | %space_id% | | name | Share space to Brian | | quota@@@state | normal | @@ -55,7 +55,7 @@ Feature: Share spaces When user "Brian" lists all available spaces via the GraphApi Then the json responded should contain a space "Unshare space" with these key and value pairs: | key | value | - | driveType | share | + | driveType | project | | id | %space_id% | | name | Unshare space | When user "Alice" unshares a space "Unshare space" to user "Brian" diff --git a/thumbnails/pkg/config/config.go b/thumbnails/pkg/config/config.go index 43071171e8..8ab2d5bfd2 100644 --- a/thumbnails/pkg/config/config.go +++ b/thumbnails/pkg/config/config.go @@ -39,7 +39,6 @@ type Thumbnail struct { FileSystemStorage FileSystemStorage `ocisConfig:"filesystem_storage"` WebdavAllowInsecure bool `ocisConfig:"webdav_allow_insecure" env:"OCIS_INSECURE;THUMBNAILS_WEBDAVSOURCE_INSECURE"` CS3AllowInsecure bool `ocisConfig:"cs3_allow_insecure" env:"OCIS_INSECURE;THUMBNAILS_CS3SOURCE_INSECURE"` - RevaGateway string `ocisConfig:"reva_gateway" env:"REVA_GATEWAY"` - WebdavNamespace string `ocisConfig:"webdav_namespace" env:"STORAGE_WEBDAV_NAMESPACE"` + RevaGateway string `ocisConfig:"reva_gateway" env:"REVA_GATEWAY"` //TODO: use REVA config FontMapFile string `ocisConfig:"font_map_file" env:"THUMBNAILS_TXT_FONTMAP_FILE"` } diff --git a/thumbnails/pkg/config/defaultconfig.go b/thumbnails/pkg/config/defaultconfig.go index 7da4bac4fd..ac2da94d29 100644 --- a/thumbnails/pkg/config/defaultconfig.go +++ b/thumbnails/pkg/config/defaultconfig.go @@ -34,7 +34,6 @@ func DefaultConfig() *Config { }, WebdavAllowInsecure: true, RevaGateway: "127.0.0.1:9142", - WebdavNamespace: "/home", CS3AllowInsecure: false, }, } diff --git a/thumbnails/pkg/service/v0/service.go b/thumbnails/pkg/service/v0/service.go index 3c1e456db2..28a0d4045f 100644 --- a/thumbnails/pkg/service/v0/service.go +++ b/thumbnails/pkg/service/v0/service.go @@ -30,8 +30,7 @@ func NewService(opts ...Option) v0proto.ThumbnailServiceHandler { logger.Fatal().Err(err).Msg("resolutions not configured correctly") } svc := Thumbnail{ - serviceID: options.Config.GRPC.Namespace + "." + options.Config.Service.Name, - webdavNamespace: options.Config.Thumbnail.WebdavNamespace, + serviceID: options.Config.GRPC.Namespace + "." + options.Config.Service.Name, manager: thumbnail.NewSimpleManager( resolutions, options.ThumbnailStorage, @@ -52,7 +51,6 @@ func NewService(opts ...Option) v0proto.ThumbnailServiceHandler { // Thumbnail implements the GRPC handler. type Thumbnail struct { serviceID string - webdavNamespace string manager thumbnail.Manager webdavSource imgsource.Source cs3Source imgsource.Source @@ -145,6 +143,7 @@ func (g Thumbnail) handleWebdavSource(ctx context.Context, req *v0proto.GetThumb } var auth, statPath string + if src.IsPublicLink { q := imgURL.Query() var rsp *gateway.AuthenticateResponse @@ -174,7 +173,7 @@ func (g Thumbnail) handleWebdavSource(ctx context.Context, req *v0proto.GetThumb statPath = path.Join("/public", src.PublicLinkToken, req.Filepath) } else { auth = src.RevaAuthorization - statPath = path.Join(g.webdavNamespace, req.Filepath) + statPath = req.Filepath } sRes, err := g.stat(statPath, auth) if err != nil { diff --git a/thumbnails/pkg/thumbnail/imgsource/cs3.go b/thumbnails/pkg/thumbnail/imgsource/cs3.go index 0727139788..9cf3db58ab 100644 --- a/thumbnails/pkg/thumbnail/imgsource/cs3.go +++ b/thumbnails/pkg/thumbnail/imgsource/cs3.go @@ -58,7 +58,7 @@ func (s CS3) Get(ctx context.Context, path string) (io.ReadCloser, error) { } var ep, tk string for _, p := range rsp.Protocols { - if p.Protocol == "simple" { + if p.Protocol == "spaces" { ep, tk = p.DownloadEndpoint, p.Token } } diff --git a/webdav/pkg/config/config.go b/webdav/pkg/config/config.go index 8b817f7f77..7c48724c22 100644 --- a/webdav/pkg/config/config.go +++ b/webdav/pkg/config/config.go @@ -19,7 +19,8 @@ type Config struct { HTTP HTTP `ocisConfig:"http"` OcisPublicURL string `ocisConfig:"ocis_public_url" env:"OCIS_URL;OCIS_PUBLIC_URL"` - WebdavNamespace string `ocisConfig:"webdav_namespace" env:"STORAGE_WEBDAV_NAMESPACE"` + WebdavNamespace string `ocisConfig:"webdav_namespace" env:"STORAGE_WEBDAV_NAMESPACE"` //TODO: prevent this cross config + RevaGateway string `ocisConfig:"reva_gateway" env:"REVA_GATEWAY"` Context context.Context } diff --git a/webdav/pkg/config/defaultconfig.go b/webdav/pkg/config/defaultconfig.go index 5edb962c4b..dcd3c04f9e 100644 --- a/webdav/pkg/config/defaultconfig.go +++ b/webdav/pkg/config/defaultconfig.go @@ -29,6 +29,7 @@ func DefaultConfig() *Config { Collector: "", }, OcisPublicURL: "https://127.0.0.1:9200", - WebdavNamespace: "/home", + WebdavNamespace: "/users/{{.Id.OpaqueId}}", + RevaGateway: "127.0.0.1:9142", } } diff --git a/webdav/pkg/dav/requests/thumbnail.go b/webdav/pkg/dav/requests/thumbnail.go index 6ce7b3d38a..be1e7d43c4 100644 --- a/webdav/pkg/dav/requests/thumbnail.go +++ b/webdav/pkg/dav/requests/thumbnail.go @@ -33,11 +33,13 @@ type ThumbnailRequest struct { Height int32 // In case of a public share the public link token. PublicLinkToken string + // The username from the requested URL + Username string } // ParseThumbnailRequest extracts all required parameters from a http request. func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) { - fp, err := extractFilePath(r) + fp, username, err := extractFilePath(r) if err != nil { return nil, err } @@ -55,6 +57,7 @@ func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) { Width: int32(width), Height: int32(height), PublicLinkToken: chi.URLParam(r, "token"), + Username: username, }, nil } @@ -64,23 +67,23 @@ func ParseThumbnailRequest(r *http.Request) (*ThumbnailRequest, error) { // // User and filepath are dynamic and filepath can contain slashes // So using the URLParam function is not possible. -func extractFilePath(r *http.Request) (string, error) { +func extractFilePath(r *http.Request) (string, string, error) { user := chi.URLParam(r, "user") user, err := url.QueryUnescape(user) if err != nil { - return "", errors.New("could not unescape user") + return "", "", errors.New("could not unescape user") } if user != "" { parts := strings.SplitN(r.URL.Path, user, 2) - return parts[1], nil + return parts[1], user, nil } token := chi.URLParam(r, "token") if token != "" { parts := strings.SplitN(r.URL.Path, token, 2) - return parts[1], nil + return parts[1], "", nil } - return "", errors.New("could not extract file path") + return "", "", errors.New("could not extract file path") } func parseDimensions(q url.Values) (int64, int64, error) { diff --git a/webdav/pkg/server/http/server.go b/webdav/pkg/server/http/server.go index bf962961bb..029245bbac 100644 --- a/webdav/pkg/server/http/server.go +++ b/webdav/pkg/server/http/server.go @@ -24,7 +24,7 @@ func Server(opts ...Option) (http.Service, error) { http.Flags(options.Flags...), ) - handle := svc.NewService( + handle, err := svc.NewService( svc.Logger(options.Logger), svc.Config(options.Config), svc.Middleware( @@ -48,6 +48,9 @@ func Server(opts ...Option) (http.Service, error) { ), ), ) + if err != nil { + return http.Service{}, err + } { handle = svc.NewInstrument(handle, options.Metrics) diff --git a/webdav/pkg/service/v0/service.go b/webdav/pkg/service/v0/service.go index 962942e6e9..64ed700d4e 100644 --- a/webdav/pkg/service/v0/service.go +++ b/webdav/pkg/service/v0/service.go @@ -3,11 +3,17 @@ package svc import ( "encoding/xml" "net/http" - "path" + "path/filepath" "strings" + gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/storage/utils/templates" "github.com/go-chi/render" merrors "go-micro.dev/v4/errors" + "google.golang.org/grpc/metadata" "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/ocis-pkg/service/grpc" @@ -38,17 +44,24 @@ type Service interface { } // NewService returns a service implementation for Service. -func NewService(opts ...Option) Service { +func NewService(opts ...Option) (Service, error) { options := newOptions(opts...) + conf := options.Config m := chi.NewMux() m.Use(options.Middleware...) + gwc, err := pool.GetGatewayServiceClient(conf.RevaGateway) + if err != nil { + return nil, err + } + svc := Webdav{ - config: options.Config, + config: conf, log: options.Logger, mux: m, thumbnailsClient: thumbnails.NewThumbnailService("com.owncloud.api.thumbnails", grpc.DefaultClient), + revaClient: gwc, } m.Route(options.Config.HTTP.Root, func(r chi.Router) { @@ -57,7 +70,7 @@ func NewService(opts ...Option) Service { r.Head("/remote.php/dav/public-files/{token}/*", svc.PublicThumbnailHead) }) - return svc + return svc, nil } // Webdav defines implements the business logic for Service. @@ -66,6 +79,7 @@ type Webdav struct { log log.Logger mux *chi.Mux thumbnailsClient thumbnails.ThumbnailService + revaClient gatewayv1beta1.GatewayAPIClient } // ServeHTTP implements the Service interface. @@ -83,6 +97,18 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) { } t := r.Header.Get(TokenHeader) + ctx := metadata.AppendToOutgoingContext(r.Context(), TokenHeader, t) + userRes, err := g.revaClient.GetUserByClaim(ctx, &userv1beta1.GetUserByClaimRequest{ + Claim: "username", + Value: tr.Username, + }) + if err != nil || userRes.Status.Code != rpcv1beta1.Code_CODE_OK { + g.log.Error().Err(err).Msg("could not get user") + renderError(w, r, errInternalError("could not get user")) + return + } + + fullPath := filepath.Join(templates.WithUser(userRes.User, g.config.WebdavNamespace), tr.Filepath) rsp, err := g.thumbnailsClient.GetThumbnail(r.Context(), &thumbnails.GetThumbnailRequest{ Filepath: strings.TrimLeft(tr.Filepath, "/"), ThumbnailType: extensionToThumbnailType(strings.TrimLeft(tr.Extension, ".")), @@ -90,7 +116,7 @@ func (g Webdav) Thumbnail(w http.ResponseWriter, r *http.Request) { Height: tr.Height, Source: &thumbnails.GetThumbnailRequest_Cs3Source{ Cs3Source: &thumbnails.CS3Source{ - Path: path.Join(g.config.WebdavNamespace, tr.Filepath), + Path: fullPath, Authorization: t, }, },