From c3e9ef41602060810b6e3dc6c8383be860109281 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 20 Apr 2020 11:45:00 +0200 Subject: [PATCH 01/43] set permissions from phoenix --- .../handlers/apps/sharing/shares/shares.go | 23 ++++++++++++++++--- pkg/publicshare/manager/memory/memory.go | 22 ++++++++---------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 6ba12d8b1f..93bd80d950 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -55,6 +55,14 @@ func (h *Handler) Init(c *config.Config) error { return nil } +// Maps oc10 permissions to roles +var ocPermToRole = map[int]string{ + 1: "viewer", + 15: "coowner", + 31: "editor", + // 5: contributor (?) +} + func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { log := appctx.GetLogger(r.Context()) @@ -281,9 +289,18 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { return } - // TODO(refs) set permissions to what phoenix sends - // TODO(refs) error handling please - testPerm, err := h.role2CS3Permissions(conversions.RoleViewer) + // phoenix sends: {"permissions": 15}. See ocPermToRole struct for mapping + permKey, err := strconv.Atoi(r.FormValue("permissions")) + if err != nil { + log.Error().Str("createShare", "shares").Msgf("invalid type: %T", permKey) + } + + perm, ok := ocPermToRole[permKey] + if !ok { + log.Error().Str("createShare", "shares").Msgf("invalid oC permission: %v", perm) + } + + testPerm, err := h.role2CS3Permissions(perm) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "invalid role", err) return diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index ab7b7f0adc..5ef24ccdcd 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -48,9 +48,8 @@ type manager struct { shares sync.Map } -// CreatePublicShare safely adds a new entry to manager.shares +// CreatePublicShare adds a new entry to manager.shares func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) { - // where could this initialization go wrong and early return? id := &link.PublicShareId{ OpaqueId: randString(12), } @@ -65,32 +64,32 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr _, passwdOk := rInfo.ArbitraryMetadata.Metadata["password"] - ctime := &typespb.Timestamp{ + createdAt := &typespb.Timestamp{ Seconds: now, Nanos: uint32(now % 1000000000), } - mtime := &typespb.Timestamp{ + modifiedAt := &typespb.Timestamp{ Seconds: now, Nanos: uint32(now % 1000000000), } - newShare := link.PublicShare{ + s := link.PublicShare{ Id: id, Owner: rInfo.GetOwner(), Creator: u.Id, ResourceId: rInfo.Id, Token: tkn, Permissions: g.Permissions, - Ctime: ctime, - Mtime: mtime, + Ctime: createdAt, + Mtime: modifiedAt, PasswordProtected: passwdOk, Expiration: g.Expiration, DisplayName: displayName, } - m.shares.Store(newShare.Token, &newShare) - return &newShare, nil + m.shares.Store(s.Token, &s) + return &s, nil } // UpdatePublicShare updates the expiration date, permissions and Mtime @@ -102,7 +101,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, ref *link token := share.GetToken() - // thread unsafe. 2 goroutines can access to the same resource? share.Permissions = g.Permissions share.Expiration = g.Expiration share.Mtime = &typespb.Timestamp{ @@ -120,7 +118,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu if ref.GetToken() != "" { share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) if err != nil { - return nil, errors.New("there are no shares for the given reference") + return nil, errors.New("no shares found") } } @@ -128,7 +126,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu if ref.GetId() != nil { share, err = m.getPublicShareByTokenID(ctx, *ref.GetId()) if err != nil { - return nil, errors.New("there are no shares for the given reference") + return nil, errors.New("no shares found") } } From 7ac248a5e4c8fa0e242d9be3b51651dd6db4d40c Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 23 Apr 2020 12:22:11 +0200 Subject: [PATCH 02/43] CRUD operations on public shares --- go.mod | 2 +- go.sum | 2 + .../services/gateway/publicshareprovider.go | 20 +- .../publicshareprovider.go | 33 +- .../handlers/apps/sharing/shares/shares.go | 225 ++++++++++++- pkg/auth/manager/publicshares/publicshares.go | 5 + pkg/publicshare/manager/memory/memory.go | 59 +++- pkg/publicshare/manager/memory/memory_test.go | 302 +++++++++--------- pkg/publicshare/publicshare.go | 3 +- 9 files changed, 467 insertions(+), 184 deletions(-) diff --git a/go.mod b/go.mod index b6d6c5a617..fbf6df67b4 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/aws/aws-sdk-go v1.30.7 github.com/cheggaaa/pb v1.0.28 github.com/coreos/go-oidc v2.2.1+incompatible - github.com/cs3org/go-cs3apis v0.0.0-20200408065125-6e23f3ecec0a + github.com/cs3org/go-cs3apis v0.0.0-20200422090600-d9e5166bebfe github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/fatih/color v1.7.0 // indirect github.com/go-openapi/strfmt v0.19.2 // indirect diff --git a/go.sum b/go.sum index a755afea1d..4fb242f88e 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20200403073321-0519c6823b48 h1:iR2JGsyZwRg6N github.com/cs3org/go-cs3apis v0.0.0-20200403073321-0519c6823b48/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20200408065125-6e23f3ecec0a h1:+enFdliTCV/aaLAvLmeka/r9wUoEypngV4JD5Gy92Uc= github.com/cs3org/go-cs3apis v0.0.0-20200408065125-6e23f3ecec0a/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20200422090600-d9e5166bebfe h1:gQgullcz2/nn1epVPhX3805nszWkSolM8m6CYLF9Y04= +github.com/cs3org/go-cs3apis v0.0.0-20200422090600-d9e5166bebfe/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index df26b263bc..85df62d5cc 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -74,6 +74,7 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar } func (s *svc) GetPublicShare(ctx context.Context, req *link.GetPublicShareRequest) (*link.GetPublicShareResponse, error) { + // TODO if the date is expired DO NOT return log := appctx.GetLogger(ctx) log.Info().Msg("get public share") @@ -106,7 +107,7 @@ func (s *svc) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRe res, err := pClient.ListPublicShares(ctx, req) if err != nil { - return nil, errors.Wrap(err, "error calling ListShares") + return nil, errors.Wrap(err, "error listing shares") } return res, nil @@ -114,10 +115,21 @@ func (s *svc) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRe func (s *svc) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShareRequest) (*link.UpdatePublicShareResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("list public share") + log.Info().Msg("update public share") - res := &link.UpdatePublicShareResponse{ - Status: status.NewOK(ctx), + pClient, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) + if err != nil { + log.Err(err).Msg("error connecting to a public share provider") + return &link.UpdatePublicShareResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_INTERNAL, + }, + }, nil + } + + res, err := pClient.UpdatePublicShare(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "error updating share") } return res, nil } diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index 820283b5e0..23d988d6c7 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -100,7 +100,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("create public share") + log.Info().Str("publicshareprovider", "create").Msg("create public share") u, ok := user.ContextGetUser(ctx) if !ok { @@ -121,7 +121,7 @@ func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicS func (s *service) RemovePublicShare(ctx context.Context, req *link.RemovePublicShareRequest) (*link.RemovePublicShareResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("remove public share") + log.Info().Str("publicshareprovider", "remove").Msg("remove public share") return &link.RemovePublicShareResponse{ Status: status.NewOK(ctx), @@ -145,17 +145,27 @@ func (s *service) GetPublicShareByToken(ctx context.Context, req *link.GetPublic func (s *service) GetPublicShare(ctx context.Context, req *link.GetPublicShareRequest) (*link.GetPublicShareResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("get public share") + log.Info().Str("publicshareprovider", "get").Msg("get public share") + + u, ok := user.ContextGetUser(ctx) + if !ok { + log.Error().Msg("error getting user from context") + } + + found, err := s.sm.GetPublicShare(ctx, u, req.Ref) + if err != nil { + return nil, err + } return &link.GetPublicShareResponse{ Status: status.NewOK(ctx), - // Share: share, + Share: found, }, nil } func (s *service) ListPublicShares(ctx context.Context, req *link.ListPublicSharesRequest) (*link.ListPublicSharesResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("list public share") + log.Info().Str("publicshareprovider", "list").Msg("list public share") user, _ := user.ContextGetUser(ctx) shares, err := s.sm.ListPublicShares(ctx, user, req.Filters, &provider.ResourceInfo{}) @@ -175,10 +185,21 @@ func (s *service) ListPublicShares(ctx context.Context, req *link.ListPublicShar func (s *service) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShareRequest) (*link.UpdatePublicShareResponse, error) { log := appctx.GetLogger(ctx) - log.Info().Msg("list public share") + log.Info().Str("publicshareprovider", "update").Msg("update public share") + + u, ok := user.ContextGetUser(ctx) + if !ok { + log.Error().Msg("error getting user from context") + } + + updateR, err := s.sm.UpdatePublicShare(ctx, u, req, nil) + if err != nil { + log.Err(err).Msgf("error updating public shares: %v", err) + } res := &link.UpdatePublicShareResponse{ Status: status.NewOK(ctx), + Share: updateR, } return res, nil } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 93bd80d950..547ab23a2c 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -25,6 +25,7 @@ import ( "net/http" "path" "strconv" + "strings" "time" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -103,9 +104,15 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } default: switch r.Method { - case "PUT": - h.updateShare(w, r, head) // TODO PUT is used with incomplete data to update a share + case "PUT": // TODO this implementation does NOT differenciates between public vs user shares. A distinction has to be made. + // update share needs to make a distinction between public / user shares + if h.isPublicShare(r, strings.ReplaceAll(head, "/", "")) { + h.updatePublicShare(w, r, strings.ReplaceAll(head, "/", "")) + } else { + h.updateShare(w, r, head) // TODO PUT is used with incomplete data to update a share + } case "DELETE": + // All CRUD operations on shares need to make a distinction between public shares and user shares. h.removeShare(w, r, head) default: response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "Only GET, POST and PUT are allowed", nil) @@ -113,6 +120,166 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +func permissionFromRequest(r *http.Request, h *Handler) *provider.ResourcePermissions { + // phoenix sends: {"permissions": 15}. See ocPermToRole struct for mapping + permKey, err := strconv.Atoi(r.FormValue("permissions")) + if err != nil { + log.Error().Str("permissionFromRequest", "shares").Msgf("invalid type: %T", permKey) + } + + perm, ok := ocPermToRole[permKey] + if !ok { + log.Error().Str("permissionFromRequest", "shares").Msgf("invalid oC permission: %v", perm) + } + + p, err := h.role2CS3Permissions(perm) + if err != nil { + } + + return p +} + +func expirationTimestampFromRequest(r *http.Request, h *Handler) *types.Timestamp { + var expireTime time.Time + var err error + + expireDate := r.FormValue("expireDate") + if expireDate != "" { + expireTime, err = time.Parse("2006-01-02T15:04:05Z0700", expireDate) + if err != nil { + log.Error().Str("expiration", "create public share").Msgf("date format invalid: %v", expireDate) + } + } + return &types.Timestamp{ + Nanos: uint32(expireTime.UnixNano()), + Seconds: uint64(expireTime.Unix()), + } +} + +func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, token string) { + updates := []*link.UpdatePublicShareRequest_Update{} + shares := make([]*conversions.ShareData, 0) + logger := appctx.GetLogger(r.Context()) + + gwC, err := pool.GetGatewayServiceClient(h.gatewayAddr) + if err != nil { + log.Err(err).Str("updatePublicShare ref:", token).Msg("updating") + response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "error getting a connection to the gateway service", nil) + return + } + + before, err := gwC.GetPublicShare(r.Context(), &link.GetPublicShareRequest{ + Ref: &link.PublicShareReference{ + Spec: &link.PublicShareReference_Id{ + Id: &link.PublicShareId{ + OpaqueId: token, + }, + }, + }, + }) + if err != nil { + response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "failed to get public share", nil) + return + } + + if r.FormValue("name") != before.GetShare().DisplayName { + updates = append(updates, &link.UpdatePublicShareRequest_Update{ + Type: link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME, + DisplayName: r.FormValue("name"), + }) + } + + // Permissions + publicSharePermissions := &link.PublicSharePermissions{ + Permissions: permissionFromRequest(r, h), + } + beforePerm, _ := json.Marshal(before.GetShare().Permissions) + afterPerm, _ := json.Marshal(publicSharePermissions) + if string(beforePerm) != string(afterPerm) { + logger.Info().Str("shares", "update").Msgf("updating permissions from %v to: %v", string(beforePerm), string(afterPerm)) + updates = append(updates, &link.UpdatePublicShareRequest_Update{ + Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, + Grant: &link.Grant{ + Permissions: publicSharePermissions, + }, + }) + } + + // ExpireDate + newExpiration := expirationTimestampFromRequest(r, h) + beforeExpiration, _ := json.Marshal(before.Share.Expiration) + afterExpiration, _ := json.Marshal(newExpiration) + if string(beforeExpiration) != string(afterExpiration) { + logger.Info().Str("shares", "update").Msgf("updating expire date from %v to: %v", string(beforeExpiration), string(afterExpiration)) + updates = append(updates, &link.UpdatePublicShareRequest_Update{ + Type: link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION, + Grant: &link.Grant{ + Expiration: newExpiration, + }, + }) + } + + // Password + if len(r.FormValue("password")) > 0 { + logger.Info().Str("shares", "update").Msg("password updated") + updates = append(updates, &link.UpdatePublicShareRequest_Update{ + Type: link.UpdatePublicShareRequest_Update_TYPE_PASSWORD, + Grant: &link.Grant{ + Password: r.FormValue("password"), + }, + }) + } + + // Updates are atomical. See: https://github.com/cs3org/cs3apis/pull/67#issuecomment-617651428 so in order to get the latest updated version + if len(updates) == 0 { + response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "There is nothing to update.", nil) // TODO(refs) error? a simple noop might suffice + return + } + + req := &link.UpdatePublicShareResponse{} + for k := range updates { + req, err = gwC.UpdatePublicShare(r.Context(), &link.UpdatePublicShareRequest{ + Ref: &link.PublicShareReference{ + Spec: &link.PublicShareReference_Id{ + Id: &link.PublicShareId{ + OpaqueId: token, + }, + }, + }, + Update: updates[k], + }) + if err != nil { + log.Err(err).Str("updatePublicShare ref:", token).Msg("sending update request to public link provider") + } + } + + statReq := provider.StatRequest{ + Ref: &provider.Reference{ + Spec: &provider.Reference_Id{ + Id: req.GetShare().GetResourceId(), + }, + }, + } + + statRes, err := gwC.Stat(r.Context(), &statReq) + if err != nil { + log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat") + response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing resource information", fmt.Errorf("error getting resource information")) + return + } + + s := conversions.PublicShare2ShareData(req.Share, r) + err = h.addFileInfo(r.Context(), s, statRes.Info) + + if err != nil { + response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error enhancing response with share data", err) + return + } + + shares = append(shares, s) + response.WriteOCSSuccess(w, r, shares) +} + func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { ctx := r.Context() log := appctx.GetLogger(ctx) @@ -300,7 +467,7 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { log.Error().Str("createShare", "shares").Msgf("invalid oC permission: %v", perm) } - testPerm, err := h.role2CS3Permissions(perm) + p, err := h.role2CS3Permissions(perm) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "invalid role", err) return @@ -310,7 +477,7 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { ResourceInfo: statRes.GetInfo(), Grant: &link.Grant{ Permissions: &link.PublicSharePermissions{ - Permissions: testPerm, + Permissions: p, }, }, } @@ -332,8 +499,8 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { // set displayname and password protected as arbitrary metadata req.ResourceInfo.ArbitraryMetadata = &provider.ArbitraryMetadata{ Metadata: map[string]string{ - "name": r.FormValue("name"), - // "password": r.FormValue("password"), + "name": r.FormValue("name"), + "password": r.FormValue("password"), }, } @@ -471,6 +638,52 @@ func (h *Handler) role2CS3Permissions(r string) (*provider.ResourcePermissions, } } +func (h *Handler) isPublicShare(r *http.Request, oid string) bool { + logger := appctx.GetLogger(r.Context()) + client, err := pool.GetGatewayServiceClient(h.gatewayAddr) + if err != nil { + logger.Err(err) + } + + psRes, err := client.GetPublicShare(r.Context(), &link.GetPublicShareRequest{ + Ref: &link.PublicShareReference{ + Spec: &link.PublicShareReference_Id{ + Id: &link.PublicShareId{ + OpaqueId: oid, + }, + }, + }, + }) + if err != nil { + logger.Err(err) + } + + if psRes.GetShare() != nil { + return true + } + + // check if we have a user share + uRes, err := client.GetShare(r.Context(), &collaboration.GetShareRequest{ + Ref: &collaboration.ShareReference{ + Spec: &collaboration.ShareReference_Id{ + Id: &collaboration.ShareId{ + OpaqueId: oid, + }, + }, + }, + }) + if err != nil { + logger.Err(err) + } + + if uRes.GetShare() != nil { + return false + } + + // TODO token is neither a public or a user share. + return false +} + func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, shareID string) { ctx := r.Context() diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index d578029338..f8f412c21b 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -78,6 +78,11 @@ func (m *manager) Authenticate(ctx context.Context, token string, secret string) return nil, err } + // how can basic auth flow be triggered from here? + if publicShareResponse.Share.GetPasswordProtected() { + return nil, errors.New("resource password protected, bearer token not found") + } + getUserResponse, err := gwConn.GetUser(ctx, &userprovider.GetUserRequest{ UserId: publicShareResponse.GetShare().GetCreator(), }) diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index 5ef24ccdcd..c82bfe9dd8 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -20,7 +20,9 @@ package memory import ( "context" + "encoding/json" "errors" + "fmt" "math/rand" "sync" "time" @@ -29,6 +31,7 @@ import ( link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/publicshare" "github.com/cs3org/reva/pkg/publicshare/manager/registry" ) @@ -48,6 +51,10 @@ type manager struct { shares sync.Map } +var ( + passwordProtected bool +) + // CreatePublicShare adds a new entry to manager.shares func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) { id := &link.PublicShareId{ @@ -62,7 +69,10 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr displayName = tkn } - _, passwdOk := rInfo.ArbitraryMetadata.Metadata["password"] + if len(rInfo.ArbitraryMetadata.Metadata["password"]) > 0 { + // TODO hash the password! + g.Password, passwordProtected = rInfo.ArbitraryMetadata.Metadata["password"] + } createdAt := &typespb.Timestamp{ Seconds: now, @@ -83,7 +93,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr Permissions: g.Permissions, Ctime: createdAt, Mtime: modifiedAt, - PasswordProtected: passwdOk, + PasswordProtected: passwordProtected, Expiration: g.Expiration, DisplayName: displayName, } @@ -93,16 +103,37 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } // UpdatePublicShare updates the expiration date, permissions and Mtime -func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference, g *link.Grant) (*link.PublicShare, error) { - share, err := m.GetPublicShare(ctx, u, ref) +func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) { + log := appctx.GetLogger(ctx) + share, err := m.GetPublicShare(ctx, u, req.Ref) if err != nil { return nil, errors.New("ref does not exist") } token := share.GetToken() - share.Permissions = g.Permissions - share.Expiration = g.Expiration + switch req.GetUpdate().GetType() { + case link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME: + log.Debug().Str("memory", "update display name").Msgf("from: `%v` to `%v`", share.DisplayName, req.Update.GetDisplayName()) + share.DisplayName = req.Update.GetDisplayName() + case link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS: + old, _ := json.Marshal(share.Permissions) + new, _ := json.Marshal(req.Update.GetGrant().Permissions) + log.Debug().Str("memory", "update grants").Msgf("from: `%v`\nto\n`%v`", old, new) + share.Permissions = req.Update.GetGrant().GetPermissions() + case link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION: + old, _ := json.Marshal(share.Expiration) + new, _ := json.Marshal(req.Update.GetGrant().Expiration) + log.Debug().Str("memory", "update expiration").Msgf("from: `%v`\nto\n`%v`", old, new) + share.Expiration = req.Update.GetGrant().Expiration + case link.UpdatePublicShareRequest_Update_TYPE_PASSWORD: + // TODO(refs) Do public shares need Grants? Struct is defined, just not used. Fill this once it's done. + fallthrough + default: + return nil, fmt.Errorf("invalid update type: %v", req.GetUpdate().GetType()) + } + + // share.Expiration = g.Expiration share.Mtime = &typespb.Timestamp{ Seconds: uint64(time.Now().Unix()), Nanos: uint32(time.Now().Unix() % 1000000000), @@ -110,7 +141,7 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, ref *link m.shares.Store(token, share) - return &link.PublicShare{}, nil + return share, nil } func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *link.PublicShare, err error) { @@ -118,7 +149,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu if ref.GetToken() != "" { share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) if err != nil { - return nil, errors.New("no shares found") + return nil, errors.New("no shares found by token") } } @@ -126,14 +157,15 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu if ref.GetId() != nil { share, err = m.getPublicShareByTokenID(ctx, *ref.GetId()) if err != nil { - return nil, errors.New("no shares found") + return nil, errors.New("no shares found by id") } } - return share, nil + return } func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { + // TODO(refs) filter out expired shares shares := []*link.PublicShare{} m.shares.Range(func(k, v interface{}) bool { s := v.(*link.PublicShare) @@ -170,7 +202,6 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin return nil, errors.New("invalid token") } -// Helpers func randString(n int) string { var l = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") b := make([]rune, n) @@ -181,19 +212,17 @@ func randString(n int) string { } func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { - // iterate over existing shares and return the first one matching the id var found *link.PublicShare m.shares.Range(func(k, v interface{}) bool { id := v.(*link.PublicShare).GetId() if targetID.String() == id.String() { found = v.(*link.PublicShare) - return true } - return false + return true }) if found != nil { return found, nil } - return nil, errors.New("invalid token") + return nil, errors.New("resource not found") } diff --git a/pkg/publicshare/manager/memory/memory_test.go b/pkg/publicshare/manager/memory/memory_test.go index 8d55c37d6e..7dc40c430e 100644 --- a/pkg/publicshare/manager/memory/memory_test.go +++ b/pkg/publicshare/manager/memory/memory_test.go @@ -18,154 +18,154 @@ package memory -import ( - "context" - "testing" - - userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" -) - -func TestMemoryProvider(t *testing.T) { - // table driven tests is perhaps more readable - // setup a new public shares manager - manager, err := New(make(map[string]interface{})) - if err != nil { - t.Error(err) - } - - // Setup dat - user := userpb.User{} - rInfo := provider.ResourceInfo{} - grant := link.Grant{} - - rInfo.ArbitraryMetadata = &provider.ArbitraryMetadata{ - Metadata: map[string]string{ - "name": "woof", - }, - } - - // create a new public share - share, _ := manager.CreatePublicShare(context.Background(), &user, &rInfo, &grant) - - // store its token for further retrieval - shareToken := share.GetToken() - - // Test updating a public share. - existingRefToken := link.PublicShareReference{ - Spec: &link.PublicShareReference_Token{ - Token: shareToken, - }, - } - - nonExistingPublicShareRef := link.PublicShareReference{ - Spec: &link.PublicShareReference_Token{Token: "somethingsomething"}, - } - - updatedMtime := &types.Timestamp{Seconds: uint64(46800)} - - newGrant := link.Grant{ - Permissions: &link.PublicSharePermissions{}, - Expiration: updatedMtime, - } - - // attempt to update an invalid public share. we expect an error - _, err = manager.UpdatePublicShare(context.Background(), &user, &nonExistingPublicShareRef, &newGrant) - if err == nil { - t.Error(err) - } - - // update an existing public share - updatedShare, err := manager.UpdatePublicShare(context.Background(), &user, &existingRefToken, &newGrant) - if err != nil { - t.Error(err) - } - - // verify the expiration was updated to 01/01/1970 @ 1:00pm (UTC) - if updatedShare.Expiration == updatedMtime { - t.Error("") - } - - // test getting an invalid token - _, err = manager.GetPublicShareByToken(context.Background(), "xxxxxxxx") - if err == nil { - t.Error(err) - } - - // test getting a valid token - fetchedPs, err := manager.GetPublicShareByToken(context.Background(), shareToken) - if err != nil { - t.Error(err) - } - - if fetchedPs.GetToken() != shareToken { - t.Error("mismatching public share tokens") - } - - // test listing public shares - listPs, err := manager.ListPublicShares(context.Background(), &user, nil, &rInfo) - if err != nil { - t.Error(err) - } - - if len(listPs) != 1 { - t.Errorf("expected list of length 1, but got %v", len(listPs)) - } - - // holds a reference of hte public share with the previously fetched token - publicShareRef := link.PublicShareReference{ - Spec: &link.PublicShareReference_Token{Token: shareToken}, - } - - // error expected - _, err = manager.GetPublicShare(context.Background(), &user, &nonExistingPublicShareRef) - if err == nil { - t.Error(err) - } - - // expected error to be nil - pShare, err := manager.GetPublicShare(context.Background(), &user, &publicShareRef) - if err != nil { - t.Error(err) - } - - existingRefID := link.PublicShareReference{ - Spec: &link.PublicShareReference_Id{ - Id: pShare.GetId(), - }, - } - - nonExistingRefID := link.PublicShareReference{ - Spec: &link.PublicShareReference_Id{ - Id: &link.PublicShareId{ - OpaqueId: "doesnt_exist", - }, - }, - } - - // get public share by ID... we don't expect an error - _, err = manager.GetPublicShare(context.Background(), &user, &existingRefID) - if err != nil { - t.Error(err) - } - - // get public share by ID... we expect an error - _, err = manager.GetPublicShare(context.Background(), &user, &nonExistingRefID) - if err == nil { - t.Error(err) - } - - // attempts to revoke a public share that does not exist, we expect an error - err = manager.RevokePublicShare(context.Background(), &user, "ref_does_not_exist") - if err == nil { - t.Error("expected a failure when revoking a public share that does not exist") - } - - // revoke an existing public share - err = manager.RevokePublicShare(context.Background(), &user, fetchedPs.GetToken()) - if err != nil { - t.Error(err) - } -} +// import ( +// "context" +// "testing" + +// userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" +// link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" +// provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +// types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" +// ) + +// func TestMemoryProvider(t *testing.T) { +// // table driven tests is perhaps more readable +// // setup a new public shares manager +// manager, err := New(make(map[string]interface{})) +// if err != nil { +// t.Error(err) +// } + +// // Setup dat +// user := userpb.User{} +// rInfo := provider.ResourceInfo{} +// grant := link.Grant{} + +// rInfo.ArbitraryMetadata = &provider.ArbitraryMetadata{ +// Metadata: map[string]string{ +// "name": "woof", +// }, +// } + +// // create a new public share +// share, _ := manager.CreatePublicShare(context.Background(), &user, &rInfo, &grant) + +// // store its token for further retrieval +// shareToken := share.GetToken() + +// // Test updating a public share. +// existingRefToken := link.PublicShareReference{ +// Spec: &link.PublicShareReference_Token{ +// Token: shareToken, +// }, +// } + +// nonExistingPublicShareRef := link.PublicShareReference{ +// Spec: &link.PublicShareReference_Token{Token: "somethingsomething"}, +// } + +// updatedMtime := &types.Timestamp{Seconds: uint64(46800)} + +// newGrant := link.Grant{ +// Permissions: &link.PublicSharePermissions{}, +// Expiration: updatedMtime, +// } + +// // attempt to update an invalid public share. we expect an error +// _, err = manager.UpdatePublicShare(context.Background(), &user, &nonExistingPublicShareRef, &newGrant) +// if err == nil { +// t.Error(err) +// } + +// // update an existing public share +// updatedShare, err := manager.UpdatePublicShare(context.Background(), &user, &existingRefToken, &newGrant) +// if err != nil { +// t.Error(err) +// } + +// // verify the expiration was updated to 01/01/1970 @ 1:00pm (UTC) +// if updatedShare.Expiration == updatedMtime { +// t.Error("") +// } + +// // test getting an invalid token +// _, err = manager.GetPublicShareByToken(context.Background(), "xxxxxxxx") +// if err == nil { +// t.Error(err) +// } + +// // test getting a valid token +// fetchedPs, err := manager.GetPublicShareByToken(context.Background(), shareToken) +// if err != nil { +// t.Error(err) +// } + +// if fetchedPs.GetToken() != shareToken { +// t.Error("mismatching public share tokens") +// } + +// // test listing public shares +// listPs, err := manager.ListPublicShares(context.Background(), &user, nil, &rInfo) +// if err != nil { +// t.Error(err) +// } + +// if len(listPs) != 1 { +// t.Errorf("expected list of length 1, but got %v", len(listPs)) +// } + +// // holds a reference of hte public share with the previously fetched token +// publicShareRef := link.PublicShareReference{ +// Spec: &link.PublicShareReference_Token{Token: shareToken}, +// } + +// // error expected +// _, err = manager.GetPublicShare(context.Background(), &user, &nonExistingPublicShareRef) +// if err == nil { +// t.Error(err) +// } + +// // expected error to be nil +// pShare, err := manager.GetPublicShare(context.Background(), &user, &publicShareRef) +// if err != nil { +// t.Error(err) +// } + +// existingRefID := link.PublicShareReference{ +// Spec: &link.PublicShareReference_Id{ +// Id: pShare.GetId(), +// }, +// } + +// nonExistingRefID := link.PublicShareReference{ +// Spec: &link.PublicShareReference_Id{ +// Id: &link.PublicShareId{ +// OpaqueId: "doesnt_exist", +// }, +// }, +// } + +// // get public share by ID... we don't expect an error +// _, err = manager.GetPublicShare(context.Background(), &user, &existingRefID) +// if err != nil { +// t.Error(err) +// } + +// // get public share by ID... we expect an error +// _, err = manager.GetPublicShare(context.Background(), &user, &nonExistingRefID) +// if err == nil { +// t.Error(err) +// } + +// // attempts to revoke a public share that does not exist, we expect an error +// err = manager.RevokePublicShare(context.Background(), &user, "ref_does_not_exist") +// if err == nil { +// t.Error("expected a failure when revoking a public share that does not exist") +// } + +// // revoke an existing public share +// err = manager.RevokePublicShare(context.Background(), &user, fetchedPs.GetToken()) +// if err != nil { +// t.Error(err) +// } +// } diff --git a/pkg/publicshare/publicshare.go b/pkg/publicshare/publicshare.go index ecef628e22..1ae441eb65 100644 --- a/pkg/publicshare/publicshare.go +++ b/pkg/publicshare/publicshare.go @@ -29,7 +29,8 @@ import ( // Manager manipulates public shares. type Manager interface { CreatePublicShare(ctx context.Context, u *user.User, md *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) - UpdatePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference, g *link.Grant) (*link.PublicShare, error) + // the only place that know about which fields to update is the request: link.UpdatePublicShareRequest. This might shift to a different data structure. + UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) RevokePublicShare(ctx context.Context, u *user.User, id string) error From 41676b31f26e155ca3d1b9fd68987f6827750d3f Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 23 Apr 2020 13:43:52 +0200 Subject: [PATCH 03/43] WIP persistent shares storage --- .../manager/filesystem/filesystem.go | 279 ++++++++++++++++++ pkg/publicshare/manager/loader/loader.go | 1 + 2 files changed, 280 insertions(+) create mode 100644 pkg/publicshare/manager/filesystem/filesystem.go diff --git a/pkg/publicshare/manager/filesystem/filesystem.go b/pkg/publicshare/manager/filesystem/filesystem.go new file mode 100644 index 0000000000..1e16a1744d --- /dev/null +++ b/pkg/publicshare/manager/filesystem/filesystem.go @@ -0,0 +1,279 @@ +// Copyright 2018-2020 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package filesystem + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/rand" + "os" + "path" + "path/filepath" + "sync" + "time" + + user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/publicshare" + "github.com/cs3org/reva/pkg/publicshare/manager/registry" + "github.com/golang/protobuf/jsonpb" +) + +func init() { + registry.Register("filesystem", New) +} + +// New returns a new memory manager. +func New(c map[string]interface{}) (publicshare.Manager, error) { + dir := ".publicshares" + + return &manager{ + m: &sync.Mutex{}, + marshaler: jsonpb.Marshaler{}, + unmarshaler: jsonpb.Unmarshaler{}, + mount: dir, + }, nil +} + +type manager struct { + m *sync.Mutex + // mount is the directory where the share files are + mount string + + marshaler jsonpb.Marshaler + unmarshaler jsonpb.Unmarshaler +} + +var ( + passwordProtected bool +) + +// CreatePublicShare adds a new entry to manager.shares +func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) { + id := &link.PublicShareId{ + OpaqueId: randString(12), + } + + tkn := randString(12) + now := uint64(time.Now().Unix()) + + displayName, ok := rInfo.ArbitraryMetadata.Metadata["name"] + if !ok { + displayName = tkn + } + + if len(rInfo.ArbitraryMetadata.Metadata["password"]) > 0 { + // TODO hash the password! + g.Password, passwordProtected = rInfo.ArbitraryMetadata.Metadata["password"] + } + + createdAt := &typespb.Timestamp{ + Seconds: now, + Nanos: uint32(now % 1000000000), + } + + modifiedAt := &typespb.Timestamp{ + Seconds: now, + Nanos: uint32(now % 1000000000), + } + + s := link.PublicShare{ + Id: id, + Owner: rInfo.GetOwner(), + Creator: u.Id, + ResourceId: rInfo.Id, + Token: tkn, + Permissions: g.Permissions, + Ctime: createdAt, + Mtime: modifiedAt, + PasswordProtected: passwordProtected, + Expiration: g.Expiration, + DisplayName: displayName, + } + + // this file could benefit of the strategy pattern. same with the memory.go driver. The only moving parts are where are the shares stored, + // but the logic of creating them remains the same. + filename := path.Join(m.mount, s.Id.OpaqueId) + // ioutil.WriteFile(filename, ) + fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700) + if err != nil { + return nil, err + } + if err := m.marshaler.Marshal(fd, &s); err != nil { + return nil, err + } + + return &s, nil +} + +// UpdatePublicShare updates the expiration date, permissions and Mtime +func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) { + log := appctx.GetLogger(ctx) + share, err := m.GetPublicShare(ctx, u, req.Ref) + if err != nil { + return nil, errors.New("ref does not exist") + } + + // token := share.GetToken() + + switch req.GetUpdate().GetType() { + case link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME: + log.Debug().Str("memory", "update display name").Msgf("from: `%v` to `%v`", share.DisplayName, req.Update.GetDisplayName()) + share.DisplayName = req.Update.GetDisplayName() + case link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS: + old, _ := json.Marshal(share.Permissions) + new, _ := json.Marshal(req.Update.GetGrant().Permissions) + log.Debug().Str("memory", "update grants").Msgf("from: `%v`\nto\n`%v`", old, new) + share.Permissions = req.Update.GetGrant().GetPermissions() + case link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION: + old, _ := json.Marshal(share.Expiration) + new, _ := json.Marshal(req.Update.GetGrant().Expiration) + log.Debug().Str("memory", "update expiration").Msgf("from: `%v`\nto\n`%v`", old, new) + share.Expiration = req.Update.GetGrant().Expiration + case link.UpdatePublicShareRequest_Update_TYPE_PASSWORD: + // TODO(refs) Do public shares need Grants? Struct is defined, just not used. Fill this once it's done. + fallthrough + default: + return nil, fmt.Errorf("invalid update type: %v", req.GetUpdate().GetType()) + } + + // share.Expiration = g.Expiration + share.Mtime = &typespb.Timestamp{ + Seconds: uint64(time.Now().Unix()), + Nanos: uint32(time.Now().Unix() % 1000000000), + } + + // m.shares.Store(token, share) + + return share, nil +} + +func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *link.PublicShare, err error) { + // Attempt to fetch public share by token + if ref.GetToken() != "" { + share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) + if err != nil { + return nil, errors.New("no shares found by token") + } + } + + // Attempt to fetch public share by Id + if ref.GetId() != nil { + share, err = m.getPublicShareByTokenID(ctx, *ref.GetId()) + if err != nil { + return nil, errors.New("no shares found by id") + } + } + + return +} + +func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { + // TODO(refs) filter out expired shares + shares := []*link.PublicShare{} + + all := []string{} + err := filepath.Walk(m.mount, func(path string, info os.FileInfo, err error) error { + all = append(all, path) + return nil + }) + if err != nil { + return nil, err + } + + for _, v := range all { + fd, err := os.Open(path.Join(m.mount, v)) + if err != nil { + return nil, err + } + + ps := link.PublicShare{} + err = m.unmarshaler.Unmarshal(fd, &ps) + if err != nil { + return nil, err + } + if len(filters) == 0 { + shares = append(shares, &ps) + } else { + for _, f := range filters { + if f.Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID { + if ps.ResourceId.StorageId == f.GetResourceId().StorageId && ps.ResourceId.OpaqueId == f.GetResourceId().OpaqueId { + shares = append(shares, &ps) + } + } + } + } + } + return shares, nil +} + +func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string) (err error) { + // // check whether the referente exists + // if _, err := m.GetPublicShareByToken(ctx, id); err != nil { + // return errors.New("reference does not exist") + // } + // m.shares.Delete(id) + return +} + +func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { + fd, err := os.Open(path.Join(m.mount, token)) + if err != nil { + return nil, err + } + + share := link.PublicShare{} + if err := m.unmarshaler.Unmarshal(fd, &share); err != nil { + return nil, err + } + + return &share, nil +} + +func randString(n int) string { + var l = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + b := make([]rune, n) + for i := range b { + b[i] = l[rand.Intn(len(l))] + } + return string(b) +} + +func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { + // var found *link.PublicShare + // m.shares.Range(func(k, v interface{}) bool { + // id := v.(*link.PublicShare).GetId() + // if targetID.String() == id.String() { + // found = v.(*link.PublicShare) + // } + // return true + // }) + + // if found != nil { + // return found, nil + // } + // return nil, errors.New("resource not found") + + return nil, nil +} diff --git a/pkg/publicshare/manager/loader/loader.go b/pkg/publicshare/manager/loader/loader.go index 1a0c86eec5..99fda5b54a 100644 --- a/pkg/publicshare/manager/loader/loader.go +++ b/pkg/publicshare/manager/loader/loader.go @@ -20,6 +20,7 @@ package loader import ( // Load core share manager drivers. + _ "github.com/cs3org/reva/pkg/publicshare/manager/filesystem" _ "github.com/cs3org/reva/pkg/publicshare/manager/memory" // Add your own here ) From bee35adced3a0c27f6aaa1fdcf34215f3d4e8de4 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 23 Apr 2020 23:08:40 +0200 Subject: [PATCH 04/43] json public share manager --- .../filesystem.go => json/json.go} | 177 ++++++++++++------ pkg/publicshare/manager/loader/loader.go | 2 +- 2 files changed, 124 insertions(+), 55 deletions(-) rename pkg/publicshare/manager/{filesystem/filesystem.go => json/json.go} (71%) diff --git a/pkg/publicshare/manager/filesystem/filesystem.go b/pkg/publicshare/manager/json/json.go similarity index 71% rename from pkg/publicshare/manager/filesystem/filesystem.go rename to pkg/publicshare/manager/json/json.go index 1e16a1744d..805f8dccd8 100644 --- a/pkg/publicshare/manager/filesystem/filesystem.go +++ b/pkg/publicshare/manager/json/json.go @@ -19,14 +19,13 @@ package filesystem import ( + "bytes" "context" "encoding/json" "errors" "fmt" + "io/ioutil" "math/rand" - "os" - "path" - "path/filepath" "sync" "time" @@ -41,25 +40,33 @@ import ( ) func init() { - registry.Register("filesystem", New) + registry.Register("json", New) } -// New returns a new memory manager. +// New returns a new filesystem public shares manager. func New(c map[string]interface{}) (publicshare.Manager, error) { - dir := ".publicshares" - return &manager{ - m: &sync.Mutex{}, + m := manager{ + mutex: &sync.Mutex{}, marshaler: jsonpb.Marshaler{}, unmarshaler: jsonpb.Unmarshaler{}, - mount: dir, - }, nil + file: "/var/tmp/.publicshares", + } + + fileContents, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + if len(fileContents) == 0 { + ioutil.WriteFile(m.file, []byte("{}"), 0644) + } + + return &m, nil } type manager struct { - m *sync.Mutex - // mount is the directory where the share files are - mount string + mutex *sync.Mutex + file string marshaler jsonpb.Marshaler unmarshaler jsonpb.Unmarshaler @@ -114,16 +121,42 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr // this file could benefit of the strategy pattern. same with the memory.go driver. The only moving parts are where are the shares stored, // but the logic of creating them remains the same. - filename := path.Join(m.mount, s.Id.OpaqueId) - // ioutil.WriteFile(filename, ) - fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700) + // write to a random file + m.mutex.Lock() + buff := bytes.Buffer{} + if err := m.marshaler.Marshal(&buff, &s); err != nil { + return nil, err + } + + // retrieve the contents of m.file as map[string]interface{} + dest := map[string]interface{}{} + fileContents, err := ioutil.ReadFile(m.file) if err != nil { return nil, err } - if err := m.marshaler.Marshal(fd, &s); err != nil { + + if err := json.Unmarshal(fileContents, &dest); err != nil { + return nil, err + } + + // insert the new key. + if _, ok := dest[s.Id.GetOpaqueId()]; !ok { + dest[s.Id.GetOpaqueId()] = buff.String() + } else { + return nil, errors.New("key already exists") + } + + // serialize dest back into JSON + destJSON, err := json.Marshal(dest) + if err != nil { return nil, err } + if err := ioutil.WriteFile(m.file, destJSON, 0644); err != nil { + return nil, err + } + + m.mutex.Unlock() return &s, nil } @@ -158,13 +191,39 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, fmt.Errorf("invalid update type: %v", req.GetUpdate().GetType()) } - // share.Expiration = g.Expiration share.Mtime = &typespb.Timestamp{ Seconds: uint64(time.Now().Unix()), Nanos: uint32(time.Now().Unix() % 1000000000), } - // m.shares.Store(token, share) + // persist share update on file + m.mutex.Lock() + db := map[string]interface{}{} + fileBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(fileBytes, &db); err != nil { + return nil, err + } + + buff := bytes.Buffer{} + if err := m.marshaler.Marshal(&buff, share); err != nil { + return nil, err + } + + // update db's old value with the updated one + db[share.GetId().OpaqueId] = buff.String() + + // write the contents of db back to the file + dbAsJSON, err := json.Marshal(db) + if err != nil { + return nil, err + } + + ioutil.WriteFile(m.file, dbAsJSON, 0644) + m.mutex.Unlock() return share, nil } @@ -192,27 +251,27 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { // TODO(refs) filter out expired shares shares := []*link.PublicShare{} + ps := link.PublicShare{} - all := []string{} - err := filepath.Walk(m.mount, func(path string, info os.FileInfo, err error) error { - all = append(all, path) - return nil - }) + // load file contents onto contents + m.mutex.Lock() + defer m.mutex.Unlock() + db := map[string]interface{}{} + fileBytes, err := ioutil.ReadFile(m.file) if err != nil { return nil, err } - for _, v := range all { - fd, err := os.Open(path.Join(m.mount, v)) - if err != nil { - return nil, err - } + if err := json.Unmarshal(fileBytes, &db); err != nil { + return nil, err + } - ps := link.PublicShare{} - err = m.unmarshaler.Unmarshal(fd, &ps) - if err != nil { + for _, v := range db { + r := bytes.NewBuffer([]byte(v.(string))) + if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { return nil, err } + if len(filters) == 0 { shares = append(shares, &ps) } else { @@ -225,6 +284,7 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } } } + return shares, nil } @@ -238,17 +298,17 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string } func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { - fd, err := os.Open(path.Join(m.mount, token)) - if err != nil { - return nil, err - } + // fd, err := os.Open(path.Join(m.file, token)) + // if err != nil { + // return nil, err + // } - share := link.PublicShare{} - if err := m.unmarshaler.Unmarshal(fd, &share); err != nil { - return nil, err - } + // share := link.PublicShare{} + // if err := m.unmarshaler.Unmarshal(fd, &share); err != nil { + // return nil, err + // } - return &share, nil + return nil, nil } func randString(n int) string { @@ -261,19 +321,28 @@ func randString(n int) string { } func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { - // var found *link.PublicShare - // m.shares.Range(func(k, v interface{}) bool { - // id := v.(*link.PublicShare).GetId() - // if targetID.String() == id.String() { - // found = v.(*link.PublicShare) - // } - // return true - // }) - - // if found != nil { - // return found, nil - // } - // return nil, errors.New("resource not found") + // load file contents onto contents + m.mutex.Lock() + defer m.mutex.Unlock() + db := map[string]interface{}{} + fileBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(fileBytes, &db); err != nil { + return nil, err + } + + if found, ok := db[targetID.GetOpaqueId()]; ok { + ps := link.PublicShare{} + r := bytes.NewBuffer([]byte(found.(string))) + if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { + return nil, err + } + + return &ps, nil + } return nil, nil } diff --git a/pkg/publicshare/manager/loader/loader.go b/pkg/publicshare/manager/loader/loader.go index 99fda5b54a..f7dbf0cfb9 100644 --- a/pkg/publicshare/manager/loader/loader.go +++ b/pkg/publicshare/manager/loader/loader.go @@ -20,7 +20,7 @@ package loader import ( // Load core share manager drivers. - _ "github.com/cs3org/reva/pkg/publicshare/manager/filesystem" + _ "github.com/cs3org/reva/pkg/publicshare/manager/json" _ "github.com/cs3org/reva/pkg/publicshare/manager/memory" // Add your own here ) From 5f8a0df10c0fccdcd06f9cbaeb69de02836ab90d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 23 Apr 2020 23:55:00 +0200 Subject: [PATCH 05/43] fix filter, add locally scoped var --- pkg/publicshare/manager/json/json.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 805f8dccd8..6ecf6a4180 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -251,11 +251,8 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { // TODO(refs) filter out expired shares shares := []*link.PublicShare{} - ps := link.PublicShare{} - // load file contents onto contents m.mutex.Lock() - defer m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -268,22 +265,24 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] for _, v := range db { r := bytes.NewBuffer([]byte(v.(string))) - if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { + local := &link.PublicShare{} + if err := m.unmarshaler.Unmarshal(r, local); err != nil { return nil, err } if len(filters) == 0 { - shares = append(shares, &ps) + shares = append(shares, local) } else { for _, f := range filters { if f.Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID { - if ps.ResourceId.StorageId == f.GetResourceId().StorageId && ps.ResourceId.OpaqueId == f.GetResourceId().OpaqueId { - shares = append(shares, &ps) + if local.ResourceId.StorageId == f.GetResourceId().StorageId && local.ResourceId.OpaqueId == f.GetResourceId().OpaqueId { + shares = append(shares, local) } } } } } + m.mutex.Unlock() return shares, nil } @@ -323,7 +322,6 @@ func randString(n int) string { func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { // load file contents onto contents m.mutex.Lock() - defer m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -343,6 +341,7 @@ func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.Pub return &ps, nil } + m.mutex.Unlock() return nil, nil } From a7bb4e6c3fae7e146f33f189557742ae64c37ac3 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 24 Apr 2020 09:09:18 +0200 Subject: [PATCH 06/43] liberate mutex on defer --- pkg/publicshare/manager/json/json.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 6ecf6a4180..a4f8c0d95a 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -123,6 +123,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr // but the logic of creating them remains the same. // write to a random file m.mutex.Lock() + m.mutex.Unlock() buff := bytes.Buffer{} if err := m.marshaler.Marshal(&buff, &s); err != nil { return nil, err @@ -155,8 +156,6 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr if err := ioutil.WriteFile(m.file, destJSON, 0644); err != nil { return nil, err } - - m.mutex.Unlock() return &s, nil } @@ -198,6 +197,7 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link // persist share update on file m.mutex.Lock() + m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -223,7 +223,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link } ioutil.WriteFile(m.file, dbAsJSON, 0644) - m.mutex.Unlock() return share, nil } @@ -253,6 +252,7 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] shares := []*link.PublicShare{} m.mutex.Lock() + m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -282,7 +282,6 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } } } - m.mutex.Unlock() return shares, nil } @@ -322,6 +321,7 @@ func randString(n int) string { func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { // load file contents onto contents m.mutex.Lock() + m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -341,7 +341,6 @@ func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.Pub return &ps, nil } - m.mutex.Unlock() return nil, nil } From 9b6cc77b8a1c3cdc9cf536bd9c0cf97e560db0ab Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 24 Apr 2020 10:28:43 +0200 Subject: [PATCH 07/43] correct time parsing on creation --- .../ocs/handlers/apps/sharing/shares/shares.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 547ab23a2c..df384f5d8d 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -150,9 +150,12 @@ func expirationTimestampFromRequest(r *http.Request, h *Handler) *types.Timestam log.Error().Str("expiration", "create public share").Msgf("date format invalid: %v", expireDate) } } + + final := expireTime.UnixNano() + return &types.Timestamp{ - Nanos: uint32(expireTime.UnixNano()), - Seconds: uint64(expireTime.Unix()), + Seconds: uint64(final / 1000000000), + Nanos: uint32(final % 1000000000), } } @@ -207,6 +210,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, toke // ExpireDate newExpiration := expirationTimestampFromRequest(r, h) + fmt.Printf("\n\n\n%+v\n\n\n", newExpiration) beforeExpiration, _ := json.Marshal(before.Share.Expiration) afterExpiration, _ := json.Marshal(newExpiration) if string(beforeExpiration) != string(afterExpiration) { @@ -482,19 +486,14 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { }, } - var expireTime time.Time expireDate := r.FormValue("expireDate") if expireDate != "" { - expireTime, err = time.Parse("2006-01-02T15:04:05Z0700", expireDate) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "invalid date format", err) return } - req.Grant.Expiration = &types.Timestamp{ - Nanos: uint32(expireTime.UnixNano()), - Seconds: uint64(expireTime.Unix()), - } } + req.Grant.Expiration = expirationTimestampFromRequest(r, h) // set displayname and password protected as arbitrary metadata req.ResourceInfo.ArbitraryMetadata = &provider.ArbitraryMetadata{ From b7499d57054eefebd250e4b9415f05e1d548f4b3 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 24 Apr 2020 11:01:23 +0200 Subject: [PATCH 08/43] hide expired public shares --- .../owncloud/ocs/handlers/apps/sharing/shares/shares.go | 2 +- pkg/publicshare/manager/json/json.go | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index df384f5d8d..be75a8e6fa 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -492,8 +492,8 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "invalid date format", err) return } + req.Grant.Expiration = expirationTimestampFromRequest(r, h) } - req.Grant.Expiration = expirationTimestampFromRequest(r, h) // set displayname and password protected as arbitrary metadata req.ResourceInfo.ArbitraryMetadata = &provider.ArbitraryMetadata{ diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index a4f8c0d95a..73f0cfa352 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -250,6 +250,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { // TODO(refs) filter out expired shares shares := []*link.PublicShare{} + now := time.Now() m.mutex.Lock() m.mutex.Unlock() @@ -275,8 +276,14 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } else { for _, f := range filters { if f.Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID { + t := time.Unix(int64(local.Expiration.GetSeconds()), int64(local.Expiration.GetNanos())) + if err != nil { + return nil, err + } if local.ResourceId.StorageId == f.GetResourceId().StorageId && local.ResourceId.OpaqueId == f.GetResourceId().OpaqueId { - shares = append(shares, local) + if (local.Expiration != nil && t.After(now)) || local.Expiration == nil { + shares = append(shares, local) + } } } } From 613e636cb36fe0cba03ffeeca6f2212dd1538d0c Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 24 Apr 2020 11:38:12 +0200 Subject: [PATCH 09/43] use correct timestamp on create and update --- pkg/publicshare/manager/json/json.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 73f0cfa352..fa378f55dc 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -83,7 +83,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } tkn := randString(12) - now := uint64(time.Now().Unix()) + now := time.Now().UnixNano() displayName, ok := rInfo.ArbitraryMetadata.Metadata["name"] if !ok { @@ -96,12 +96,12 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } createdAt := &typespb.Timestamp{ - Seconds: now, + Seconds: uint64(now / 1000000000), Nanos: uint32(now % 1000000000), } modifiedAt := &typespb.Timestamp{ - Seconds: now, + Seconds: uint64(now / 1000000000), Nanos: uint32(now % 1000000000), } @@ -167,6 +167,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, errors.New("ref does not exist") } + now := time.Now().UnixNano() + // token := share.GetToken() switch req.GetUpdate().GetType() { @@ -191,8 +193,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link } share.Mtime = &typespb.Timestamp{ - Seconds: uint64(time.Now().Unix()), - Nanos: uint32(time.Now().Unix() % 1000000000), + Seconds: uint64(now / 1000000000), + Nanos: uint32(now % 1000000000), } // persist share update on file From 9cdada675bb0ef2a67cd270a27d66ee5688e348b Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 24 Apr 2020 11:52:23 +0200 Subject: [PATCH 10/43] add comment for future generations --- pkg/publicshare/manager/memory/memory.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index c82bfe9dd8..00cc55cd95 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -145,6 +145,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link } func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *link.PublicShare, err error) { + // TODO(refs) return an error if the share is expired. + // Attempt to fetch public share by token if ref.GetToken() != "" { share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) From c1cb7935d892d27ec8a94b58627971a105424496 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 27 Apr 2020 09:46:25 +0200 Subject: [PATCH 11/43] get shares by token working --- pkg/publicshare/manager/json/json.go | 37 +++++++++++++++++----------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index fa378f55dc..e25923a3ec 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -197,7 +197,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link Nanos: uint32(now % 1000000000), } - // persist share update on file m.mutex.Lock() m.mutex.Unlock() db := map[string]interface{}{} @@ -215,10 +214,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, err } - // update db's old value with the updated one db[share.GetId().OpaqueId] = buff.String() - // write the contents of db back to the file dbAsJSON, err := json.Marshal(db) if err != nil { return nil, err @@ -257,12 +254,12 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] m.mutex.Lock() m.mutex.Unlock() db := map[string]interface{}{} - fileBytes, err := ioutil.ReadFile(m.file) + readBytes, err := ioutil.ReadFile(m.file) if err != nil { return nil, err } - if err := json.Unmarshal(fileBytes, &db); err != nil { + if err := json.Unmarshal(readBytes, &db); err != nil { return nil, err } @@ -305,17 +302,29 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string } func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { - // fd, err := os.Open(path.Join(m.file, token)) - // if err != nil { - // return nil, err - // } + db := map[string]interface{}{} + readBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } - // share := link.PublicShare{} - // if err := m.unmarshaler.Unmarshal(fd, &share); err != nil { - // return nil, err - // } + if err := json.Unmarshal(readBytes, &db); err != nil { + return nil, err + } - return nil, nil + for _, v := range db { + r := bytes.NewBuffer([]byte(v.(string))) + local := &link.PublicShare{} + if err := m.unmarshaler.Unmarshal(r, local); err != nil { + return nil, err + } + + if local.Token == token { + return local, nil + } + } + + return nil, fmt.Errorf("share with token: `%v` not found", token) } func randString(n int) string { From bb642fa185116869a3bd0e6bbc852eb6491fad6c Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 27 Apr 2020 10:00:26 +0200 Subject: [PATCH 12/43] defer mutex unlock, refactor GetShare --- pkg/publicshare/manager/json/json.go | 57 +++++++++++----------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index e25923a3ec..dae3236ed1 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -123,7 +123,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr // but the logic of creating them remains the same. // write to a random file m.mutex.Lock() - m.mutex.Unlock() + defer m.mutex.Unlock() buff := bytes.Buffer{} if err := m.marshaler.Marshal(&buff, &s); err != nil { return nil, err @@ -198,7 +198,7 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link } m.mutex.Lock() - m.mutex.Unlock() + defer m.mutex.Unlock() db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -235,12 +235,26 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu } } - // Attempt to fetch public share by Id - if ref.GetId() != nil { - share, err = m.getPublicShareByTokenID(ctx, *ref.GetId()) - if err != nil { - return nil, errors.New("no shares found by id") + m.mutex.Lock() + defer m.mutex.Unlock() + db := map[string]interface{}{} + fileBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(fileBytes, &db); err != nil { + return nil, err + } + + if found, ok := db[ref.GetId().GetOpaqueId()]; ok { + ps := link.PublicShare{} + r := bytes.NewBuffer([]byte(found.(string))) + if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { + return nil, err } + + return &ps, nil } return @@ -252,7 +266,7 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] now := time.Now() m.mutex.Lock() - m.mutex.Unlock() + defer m.mutex.Unlock() db := map[string]interface{}{} readBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -335,30 +349,3 @@ func randString(n int) string { } return string(b) } - -func (m *manager) getPublicShareByTokenID(ctx context.Context, targetID link.PublicShareId) (*link.PublicShare, error) { - // load file contents onto contents - m.mutex.Lock() - m.mutex.Unlock() - db := map[string]interface{}{} - fileBytes, err := ioutil.ReadFile(m.file) - if err != nil { - return nil, err - } - - if err := json.Unmarshal(fileBytes, &db); err != nil { - return nil, err - } - - if found, ok := db[targetID.GetOpaqueId()]; ok { - ps := link.PublicShare{} - r := bytes.NewBuffer([]byte(found.(string))) - if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { - return nil, err - } - - return &ps, nil - } - - return nil, nil -} From 2ad8bf114fd75e110d49e81f293a62aa9864963d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 27 Apr 2020 10:02:47 +0200 Subject: [PATCH 13/43] use mutex on get public share --- pkg/publicshare/manager/json/json.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index dae3236ed1..84aa72155b 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -124,6 +124,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr // write to a random file m.mutex.Lock() defer m.mutex.Unlock() + buff := bytes.Buffer{} if err := m.marshaler.Marshal(&buff, &s); err != nil { return nil, err @@ -199,6 +200,7 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link m.mutex.Lock() defer m.mutex.Unlock() + db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -237,6 +239,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu m.mutex.Lock() defer m.mutex.Unlock() + db := map[string]interface{}{} fileBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -261,12 +264,12 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu } func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { - // TODO(refs) filter out expired shares shares := []*link.PublicShare{} now := time.Now() m.mutex.Lock() defer m.mutex.Unlock() + db := map[string]interface{}{} readBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -306,13 +309,8 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] return shares, nil } -func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string) (err error) { - // // check whether the referente exists - // if _, err := m.GetPublicShareByToken(ctx, id); err != nil { - // return errors.New("reference does not exist") - // } - // m.shares.Delete(id) - return +func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string) error { + return fmt.Errorf("RevokePublicShare method unimplemented") } func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { @@ -326,6 +324,9 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin return nil, err } + m.mutex.Lock() + defer m.mutex.Unlock() + for _, v := range db { r := bytes.NewBuffer([]byte(v.(string))) local := &link.PublicShare{} From 8503ee313d3f5d75eb6253c15dea840bbe379b0a Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 27 Apr 2020 10:13:17 +0200 Subject: [PATCH 14/43] code style --- pkg/publicshare/manager/json/json.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 84aa72155b..37ae7e2ffd 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -119,9 +119,6 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr DisplayName: displayName, } - // this file could benefit of the strategy pattern. same with the memory.go driver. The only moving parts are where are the shares stored, - // but the logic of creating them remains the same. - // write to a random file m.mutex.Lock() defer m.mutex.Unlock() @@ -130,26 +127,23 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr return nil, err } - // retrieve the contents of m.file as map[string]interface{} - dest := map[string]interface{}{} + db := map[string]interface{}{} fileContents, err := ioutil.ReadFile(m.file) if err != nil { return nil, err } - if err := json.Unmarshal(fileContents, &dest); err != nil { + if err := json.Unmarshal(fileContents, &db); err != nil { return nil, err } - // insert the new key. - if _, ok := dest[s.Id.GetOpaqueId()]; !ok { - dest[s.Id.GetOpaqueId()] = buff.String() + if _, ok := db[s.Id.GetOpaqueId()]; !ok { + db[s.Id.GetOpaqueId()] = buff.String() } else { return nil, errors.New("key already exists") } - // serialize dest back into JSON - destJSON, err := json.Marshal(dest) + destJSON, err := json.Marshal(db) if err != nil { return nil, err } @@ -160,7 +154,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr return &s, nil } -// UpdatePublicShare updates the expiration date, permissions and Mtime +// UpdatePublicShare updates the public share func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) { log := appctx.GetLogger(ctx) share, err := m.GetPublicShare(ctx, u, req.Ref) @@ -170,8 +164,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link now := time.Now().UnixNano() - // token := share.GetToken() - switch req.GetUpdate().GetType() { case link.UpdatePublicShareRequest_Update_TYPE_DISPLAYNAME: log.Debug().Str("memory", "update display name").Msgf("from: `%v` to `%v`", share.DisplayName, req.Update.GetDisplayName()) @@ -187,7 +179,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link log.Debug().Str("memory", "update expiration").Msgf("from: `%v`\nto\n`%v`", old, new) share.Expiration = req.Update.GetGrant().Expiration case link.UpdatePublicShareRequest_Update_TYPE_PASSWORD: - // TODO(refs) Do public shares need Grants? Struct is defined, just not used. Fill this once it's done. fallthrough default: return nil, fmt.Errorf("invalid update type: %v", req.GetUpdate().GetType()) @@ -228,8 +219,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return share, nil } +// GetPublicShare gets a public share either by ID or Token. func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *link.PublicShare, err error) { - // Attempt to fetch public share by token if ref.GetToken() != "" { share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) if err != nil { @@ -263,6 +254,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu return } +// ListPublicShares retrieves all the shares on the manager that are valid. func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { shares := []*link.PublicShare{} now := time.Now() @@ -309,10 +301,12 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] return shares, nil } +// RevokePublicShare undocumented. func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string) error { return fmt.Errorf("RevokePublicShare method unimplemented") } +// GetPublicShareByToken gets a public share by its opaque token. func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { db := map[string]interface{}{} readBytes, err := ioutil.ReadFile(m.file) @@ -342,6 +336,7 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin return nil, fmt.Errorf("share with token: `%v` not found", token) } +// randString is a helper to create tokens. It could be a token manager instead. func randString(n int) string { var l = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") b := make([]rune, n) From ac9ab44cf0f7e847baa518643ac619f1a85fd849 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 27 Apr 2020 14:02:01 +0200 Subject: [PATCH 15/43] address linter --- .../ocs/handlers/apps/sharing/shares/shares.go | 1 + pkg/publicshare/manager/json/json.go | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index cecebe6fad..9d44b3832d 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -153,6 +153,7 @@ func permissionFromRequest(r *http.Request, h *Handler) *provider.ResourcePermis p, err := h.role2CS3Permissions(perm) if err != nil { + log.Error().Str("permissionFromRequest", "shares").Msgf("role to cs3permission %v", perm) } return p diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 37ae7e2ffd..2f284be57e 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -50,7 +50,7 @@ func New(c map[string]interface{}) (publicshare.Manager, error) { mutex: &sync.Mutex{}, marshaler: jsonpb.Marshaler{}, unmarshaler: jsonpb.Unmarshaler{}, - file: "/var/tmp/.publicshares", + file: "/var/tmp/.publicshares", // TODO MUST be configurable. } fileContents, err := ioutil.ReadFile(m.file) @@ -58,7 +58,10 @@ func New(c map[string]interface{}) (publicshare.Manager, error) { return nil, err } if len(fileContents) == 0 { - ioutil.WriteFile(m.file, []byte("{}"), 0644) + err := ioutil.WriteFile(m.file, []byte("{}"), 0644) + if err != nil { + return nil, err + } } return &m, nil @@ -214,7 +217,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, err } - ioutil.WriteFile(m.file, dbAsJSON, 0644) + if err := ioutil.WriteFile(m.file, dbAsJSON, 0644); err != nil { + return nil, err + } return share, nil } From 6c84f2a55479a04a85289ca28a5071da4b299eab Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 28 Apr 2020 17:20:37 +0200 Subject: [PATCH 16/43] navigation working --- .../grpc/services/gateway/storageprovider.go | 26 ++++++- .../publicstorageprovider.go | 69 ++++++++++++------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 63ffb083c7..0d93da5e71 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -376,10 +376,30 @@ func (s *svc) initiateFileUpload(ctx context.Context, req *provider.InitiateFile } func (s *svc) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provider.GetPathResponse, error) { - res := &provider.GetPathResponse{ - Status: status.NewUnimplemented(ctx, nil, "GetPath not yet implemented"), + ref := &provider.Reference{ + Spec: &provider.Reference_Id{ + Id: req.ResourceId, + }, } - return res, nil + + statReq := &provider.StatRequest{ + Ref: ref, + } + res, err := s.stat(ctx, statReq) + if err != nil { + err = errors.Wrap(err, "gateway: error stating ref:"+ref.String()) + return nil, err + } + + if res.Status.Code != rpc.Code_CODE_OK { + err := status.NewErrorFromCode(res.Status.Code, "gateway") + return nil, err + } + + return &provider.GetPathResponse{ + Status: res.Status, + Path: res.GetInfo().GetPath(), + }, nil } func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 7012f3b96e..3ce7eb9f18 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -146,7 +146,12 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide trace.StringAttribute("ref", req.Ref.String()), ) - refFromReq, err := s.refFromRequest(ctx, req) + tkn, relativePath, err := s.unwrap(ctx, req.Ref) + if err != nil { + return nil, err + } + + pathFromToken, err := s.pathFromToken(ctx, tkn) if err != nil { return nil, err } @@ -154,13 +159,26 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide statResponse, err := s.gateway.Stat( ctx, &provider.StatRequest{ - Ref: refFromReq, + Ref: &provider.Reference{ + Spec: &provider.Reference_Path{ + Path: path.Join("/", pathFromToken, relativePath), + }, + }, }) if err != nil { log.Error().Err(err).Msg("error during stat call") return nil, err } + // we don't want to leak the path + statResponse.Info.Path = path.Join("/", tkn, relativePath) + + // if statResponse.Status.Code != rpc.Code_CODE_OK { + // if statResponse.Status.Code == rpc.Code_CODE_NOT_FOUND { + // // log.Warn().Str("path", refFromToken.GetPath()).Msgf("resource: `%v` not found", refFromToken.GetId()) + // } + // } + return statResponse, nil } @@ -169,7 +187,12 @@ func (s *service) ListContainerStream(req *provider.ListContainerStreamRequest, } func (s *service) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { - statResponse, err := s.Stat(ctx, &provider.StatRequest{Ref: req.Ref}) + tkn, relativePath, err := s.unwrap(ctx, req.Ref) + if err != nil { + return nil, err + } + + pathFromToken, err := s.pathFromToken(ctx, tkn) if err != nil { return nil, err } @@ -178,8 +201,8 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer ctx, &provider.ListContainerRequest{ Ref: &provider.Reference{ - Spec: &provider.Reference_Id{ - Id: statResponse.GetInfo().GetId(), + Spec: &provider.Reference_Path{ + Path: path.Join("/", pathFromToken, relativePath), }, }, }, @@ -187,6 +210,11 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer if err != nil { return nil, err } + + for i := range listContainerR.Infos { + listContainerR.Infos[i].Path = path.Join("/", tkn, relativePath, path.Base(listContainerR.Infos[i].Path)) + } + return listContainerR, nil } @@ -272,31 +300,22 @@ func (s *service) trimMountPrefix(fn string) (string, error) { return "", errors.New(fmt.Sprintf("path=%q does not belong to this storage provider mount path=%q"+fn, s.mountPath)) } -// refFromRequest returns a reference from a public share token. -func (s *service) refFromRequest(ctx context.Context, req *provider.StatRequest) (*provider.Reference, error) { - ctx, span := trace.StartSpan(ctx, "refFromRequest") - defer span.End() - - span.AddAttributes( - trace.StringAttribute("ref", req.Ref.String()), - ) - - token, _, err := s.unwrap(ctx, req.Ref) - if err != nil { - return nil, err - } - +// pathFromToken returns a reference from a public share token. +func (s *service) pathFromToken(ctx context.Context, token string) (string, error) { publicShareResponse, err := s.gateway.GetPublicShareByToken( ctx, &link.GetPublicShareByTokenRequest{Token: token}, ) if err != nil { - return nil, err + return "", err } - return &provider.Reference{ - Spec: &provider.Reference_Id{ - Id: publicShareResponse.GetShare().ResourceId, - }, - }, nil + pathRes, err := s.gateway.GetPath(ctx, &provider.GetPathRequest{ + ResourceId: publicShareResponse.GetShare().GetResourceId(), + }) + if err != nil { + return "", err + } + + return pathRes.Path, nil } From 6c118b2831af4ac83a2d70f317fd2c1c69926b97 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 28 Apr 2020 23:31:53 +0200 Subject: [PATCH 17/43] folder navigation on a public share is now supported --- .../services/gateway/publicshareprovider.go | 55 +++++++++++++++++++ .../storageprovider/storageprovider.go | 39 +++++++++++-- internal/http/services/owncloud/ocdav/dav.go | 20 +++---- .../handlers/apps/sharing/shares/shares.go | 17 +++--- pkg/auth/manager/publicshares/publicshares.go | 16 ++++-- pkg/publicshare/manager/json/json.go | 5 ++ pkg/publicshare/manager/memory/memory.go | 6 +- 7 files changed, 125 insertions(+), 33 deletions(-) diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 85df62d5cc..9921f45a91 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -43,6 +43,61 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } + // Grants are not accessible through a link.PublicShare, in order for a service to access a grant (link.Grant) this needs to be + // commited to the Storage, for later retrievals. The following intends to do just that. + + // TODO(labkode): if both commits are enabled they could be done concurrently. + // if s.c.CommitShareToStorageGrant { + // raw, err := json.Marshal(req.Grant) + // if err != nil { + // return nil, err + // } + + // grantReq := &provider.AddGrantRequest{ + // Ref: &provider.Reference{ + // Spec: &provider.Reference_Id{ + // Id: req.ResourceInfo.Id, + // }, + // }, + // Grant: &provider.Grant{ + // Permissions: req.Grant.Permissions.Permissions, + // }, + // Opaque: &typesv1beta1.Opaque{ + // Map: map[string]*typesv1beta1.OpaqueEntry{ + // "grant": &typesv1beta1.OpaqueEntry{ + // Decoder: "json", + // Value: raw, + // }, + // }, + // }, + // } + + // log.Info().Interface("grantReq", grantReq).Msg("commiting share to storage grant") + + // c, err := s.findByID(ctx, req.ResourceInfo.Id) + // if err != nil { + // if _, ok := err.(errtypes.IsNotFound); ok { + // return &link.CreatePublicShareResponse{ + // Status: status.NewNotFound(ctx, "storage provider not found"), + // }, nil + // } + // return &link.CreatePublicShareResponse{ + // Status: status.NewInternal(ctx, err, "error finding storage provider"), + // }, nil + // } + + // grantRes, err := c.AddGrant(ctx, grantReq) + // if err != nil { + // return nil, errors.Wrap(err, "gateway: error calling AddGrant") + // } + // if grantRes.Status.Code != rpc.Code_CODE_OK { + // return &link.CreatePublicShareResponse{ + // Status: status.NewInternal(ctx, status.NewErrorFromCode(grantRes.Status.Code, "gateway"), + // "error committing share to storage grant"), + // }, nil + // } + // } + // TODO(refs) commit to storage if configured return res, nil } diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index e767d3a99d..e185d498ff 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -20,6 +20,7 @@ package storageprovider import ( "context" + // "encoding/json" "fmt" "net/url" "os" @@ -27,6 +28,7 @@ import ( "strings" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + // link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" @@ -657,18 +659,43 @@ func (s *service) ListGrants(ctx context.Context, req *provider.ListGrantsReques return nil, nil } +const ( + ContextGrant = iota +) + func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) (*provider.AddGrantResponse, error) { - // check grantee type is valid - if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_INVALID { + newRef, err := s.unwrap(ctx, req.Ref) + if err != nil { return &provider.AddGrantResponse{ - Status: status.NewInvalid(ctx, "grantee type is invalid"), + Status: status.NewInternal(ctx, err, "error unwrapping path"), }, nil } + // check if there is an opaque grant + // if req.GetOpaque() != nil { + // linkGrant := link.Grant{} + // val := req.GetOpaque().GetMap() + // if grantFromOpaque, ok := val["grant"]; ok { + // // TODO need to use map decoder. + // json.Unmarshal(grantFromOpaque.Value, &linkGrant) + // } + + // err := s.storage.AddGrant(ctx, newRef, nil) + // if err != nil { + // return &provider.AddGrantResponse{ + // Status: status.NewInternal(ctx, err, "error setting ACL"), + // }, nil + // } + + // res := &provider.AddGrantResponse{ + // Status: status.NewOK(ctx), + // } + // return res, nil + // } - newRef, err := s.unwrap(ctx, req.Ref) - if err != nil { + // check grantee type is valid + if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_INVALID { return &provider.AddGrantResponse{ - Status: status.NewInternal(ctx, err, "error unwrapping path"), + Status: status.NewInvalid(ctx, "grantee type is invalid"), }, nil } diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 3e3ace6160..879a9fd66c 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -24,7 +24,6 @@ import ( "path" gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" - typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" tokenpkg "github.com/cs3org/reva/pkg/token" @@ -101,21 +100,18 @@ func (h *DavHandler) Handler(s *svc) http.Handler { w.WriteHeader(http.StatusNotFound) } + _, pass, _ := r.BasicAuth() + token, _ := router.ShiftPath(r.URL.Path) + authenticateRequest := gatewayv1beta1.AuthenticateRequest{ - Type: "publicshares", - ClientId: r.URL.Path, - Opaque: &typesv1beta1.Opaque{ - Map: map[string]*typesv1beta1.OpaqueEntry{ - "token": &typesv1beta1.OpaqueEntry{ - Value: []byte(r.URL.Path), - }, - }, - }, + Type: "publicshares", + ClientId: token, + ClientSecret: pass, } res, err := c.Authenticate(r.Context(), &authenticateRequest) - if err != nil { - w.WriteHeader(http.StatusNotFound) + if err != nil { // TODO we might need to return not found. Do error assertion on err. + w.WriteHeader(http.StatusUnauthorized) } ctx := context.WithValue(ctx, ctxKeyBaseURI, base) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 9d44b3832d..82ab50a33d 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -169,14 +169,15 @@ func expirationTimestampFromRequest(r *http.Request, h *Handler) *types.Timestam if err != nil { log.Error().Str("expiration", "create public share").Msgf("date format invalid: %v", expireDate) } - } - - final := expireTime.UnixNano() + final := expireTime.UnixNano() - return &types.Timestamp{ - Seconds: uint64(final / 1000000000), - Nanos: uint32(final % 1000000000), + return &types.Timestamp{ + Seconds: uint64(final / 1000000000), + Nanos: uint32(final % 1000000000), + } } + + return nil } func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, token string) { @@ -230,10 +231,9 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, toke // ExpireDate newExpiration := expirationTimestampFromRequest(r, h) - fmt.Printf("\n\n\n%+v\n\n\n", newExpiration) beforeExpiration, _ := json.Marshal(before.Share.Expiration) afterExpiration, _ := json.Marshal(newExpiration) - if string(beforeExpiration) != string(afterExpiration) { + if newExpiration != nil || (string(afterExpiration) != string(beforeExpiration)) { logger.Info().Str("shares", "update").Msgf("updating expire date from %v to: %v", string(beforeExpiration), string(afterExpiration)) updates = append(updates, &link.UpdatePublicShareRequest_Update{ Type: link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION, @@ -503,6 +503,7 @@ func (h *Handler) createShare(w http.ResponseWriter, r *http.Request) { Permissions: &link.PublicSharePermissions{ Permissions: p, }, + Password: r.FormValue("password"), }, } diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index f8f412c21b..7b333b1496 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -20,11 +20,11 @@ package publicshares import ( "context" - "strings" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" userprovider "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" + typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -66,20 +66,28 @@ func New(m map[string]interface{}) (auth.Manager, error) { } func (m *manager) Authenticate(ctx context.Context, token string, secret string) (*user.User, error) { - parts := strings.Split(token, "/") - gwConn, err := pool.GetGatewayServiceClient(m.c.GatewayAddr) if err != nil { return nil, err } - publicShareResponse, err := gwConn.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{Token: parts[1]}) + publicShareResponse, err := gwConn.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ + Token: token, + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "password": &typesv1beta1.OpaqueEntry{ + Value: []byte(secret), + }, + }, + }, + }) if err != nil { return nil, err } // how can basic auth flow be triggered from here? if publicShareResponse.Share.GetPasswordProtected() { + // publicShareResponse.GetShare(). return nil, errors.New("resource password protected, bearer token not found") } diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 2f284be57e..a22b574c30 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -165,6 +165,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, errors.New("ref does not exist") } + fmt.Printf("\n\n\nafter get:\n%+v\n\n\n", share.Expiration) + now := time.Now().UnixNano() switch req.GetUpdate().GetType() { @@ -177,6 +179,7 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link log.Debug().Str("memory", "update grants").Msgf("from: `%v`\nto\n`%v`", old, new) share.Permissions = req.Update.GetGrant().GetPermissions() case link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION: + fmt.Printf("\n\n\ngot expiration update type:\n%+v\n\n\n", req.Update.GetGrant().Expiration) old, _ := json.Marshal(share.Expiration) new, _ := json.Marshal(req.Update.GetGrant().Expiration) log.Debug().Str("memory", "update expiration").Msgf("from: `%v`\nto\n`%v`", old, new) @@ -210,6 +213,8 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, err } + fmt.Printf("\n\n\n saving:\n%+v\n\n\n", share.Expiration) + db[share.GetId().OpaqueId] = buff.String() dbAsJSON, err := json.Marshal(db) diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index 00cc55cd95..1f11f4d924 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -69,9 +69,8 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr displayName = tkn } - if len(rInfo.ArbitraryMetadata.Metadata["password"]) > 0 { - // TODO hash the password! - g.Password, passwordProtected = rInfo.ArbitraryMetadata.Metadata["password"] + if g.Password != "" { + passwordProtected = true } createdAt := &typespb.Timestamp{ @@ -201,6 +200,7 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin if ps, ok := m.shares.Load(token); ok { return ps.(*link.PublicShare), nil } + fmt.Printf("\n\n\nHERE\n\n\n") return nil, errors.New("invalid token") } From a8fe9eee258626b57568945cb260f757ad764afa Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 29 Apr 2020 08:19:27 +0200 Subject: [PATCH 18/43] remove spurious lines --- pkg/publicshare/manager/json/json.go | 5 ----- pkg/publicshare/manager/memory/memory.go | 1 - 2 files changed, 6 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index a22b574c30..2f284be57e 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -165,8 +165,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, errors.New("ref does not exist") } - fmt.Printf("\n\n\nafter get:\n%+v\n\n\n", share.Expiration) - now := time.Now().UnixNano() switch req.GetUpdate().GetType() { @@ -179,7 +177,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link log.Debug().Str("memory", "update grants").Msgf("from: `%v`\nto\n`%v`", old, new) share.Permissions = req.Update.GetGrant().GetPermissions() case link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION: - fmt.Printf("\n\n\ngot expiration update type:\n%+v\n\n\n", req.Update.GetGrant().Expiration) old, _ := json.Marshal(share.Expiration) new, _ := json.Marshal(req.Update.GetGrant().Expiration) log.Debug().Str("memory", "update expiration").Msgf("from: `%v`\nto\n`%v`", old, new) @@ -213,8 +210,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return nil, err } - fmt.Printf("\n\n\n saving:\n%+v\n\n\n", share.Expiration) - db[share.GetId().OpaqueId] = buff.String() dbAsJSON, err := json.Marshal(db) diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index 1f11f4d924..d1968ad14d 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -200,7 +200,6 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin if ps, ok := m.shares.Load(token); ok { return ps.(*link.PublicShare), nil } - fmt.Printf("\n\n\nHERE\n\n\n") return nil, errors.New("invalid token") } From da5a7d22fef43ee403107047aa4db28c31d826b2 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 29 Apr 2020 09:32:26 +0200 Subject: [PATCH 19/43] attempt to create db file if not exists --- pkg/publicshare/manager/json/json.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 2f284be57e..cfc81fd278 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -26,6 +26,7 @@ import ( "fmt" "io/ioutil" "math/rand" + "os" "sync" "time" @@ -53,6 +54,13 @@ func New(c map[string]interface{}) (publicshare.Manager, error) { file: "/var/tmp/.publicshares", // TODO MUST be configurable. } + // attempt to create the db file + if _, err := os.Stat(m.file); err != nil { + if _, err := os.Create(m.file); err != nil { + return nil, err + } + } + fileContents, err := ioutil.ReadFile(m.file) if err != nil { return nil, err From b160fcd021be5fcfec49fa9a7dedcea1d439c7e5 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 29 Apr 2020 09:38:26 +0200 Subject: [PATCH 20/43] base64 encode password --- pkg/publicshare/manager/json/json.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index cfc81fd278..9f0bd3d70b 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -21,6 +21,7 @@ package filesystem import ( "bytes" "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -102,8 +103,9 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } if len(rInfo.ArbitraryMetadata.Metadata["password"]) > 0 { - // TODO hash the password! - g.Password, passwordProtected = rInfo.ArbitraryMetadata.Metadata["password"] + msg := "public:" + rInfo.ArbitraryMetadata.Metadata["password"] + g.Password = base64.StdEncoding.EncodeToString([]byte(msg)) + passwordProtected = true } createdAt := &typespb.Timestamp{ From 52c9d2db9c6bcbc71a7eee80f9a2ddd536e112c4 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 8 May 2020 11:49:10 +0200 Subject: [PATCH 21/43] in memory grant manager as a proof of concept --- .../services/gateway/publicshareprovider.go | 88 +++++++------------ .../publicstorageprovider.go | 17 +++- internal/http/services/owncloud/ocdav/dav.go | 11 +-- pkg/auth/manager/publicshares/publicshares.go | 13 ++- 4 files changed, 54 insertions(+), 75 deletions(-) diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 9921f45a91..aef9bdcba1 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -20,6 +20,7 @@ package gateway import ( "context" + "fmt" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" @@ -29,6 +30,11 @@ import ( "github.com/pkg/errors" ) +var ( + // maps public share tokens to its grants. + grants = map[string]*link.Grant{} +) + func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { log := appctx.GetLogger(ctx) log.Info().Msg("create public share") @@ -43,62 +49,9 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - // Grants are not accessible through a link.PublicShare, in order for a service to access a grant (link.Grant) this needs to be - // commited to the Storage, for later retrievals. The following intends to do just that. - - // TODO(labkode): if both commits are enabled they could be done concurrently. - // if s.c.CommitShareToStorageGrant { - // raw, err := json.Marshal(req.Grant) - // if err != nil { - // return nil, err - // } - - // grantReq := &provider.AddGrantRequest{ - // Ref: &provider.Reference{ - // Spec: &provider.Reference_Id{ - // Id: req.ResourceInfo.Id, - // }, - // }, - // Grant: &provider.Grant{ - // Permissions: req.Grant.Permissions.Permissions, - // }, - // Opaque: &typesv1beta1.Opaque{ - // Map: map[string]*typesv1beta1.OpaqueEntry{ - // "grant": &typesv1beta1.OpaqueEntry{ - // Decoder: "json", - // Value: raw, - // }, - // }, - // }, - // } - - // log.Info().Interface("grantReq", grantReq).Msg("commiting share to storage grant") - - // c, err := s.findByID(ctx, req.ResourceInfo.Id) - // if err != nil { - // if _, ok := err.(errtypes.IsNotFound); ok { - // return &link.CreatePublicShareResponse{ - // Status: status.NewNotFound(ctx, "storage provider not found"), - // }, nil - // } - // return &link.CreatePublicShareResponse{ - // Status: status.NewInternal(ctx, err, "error finding storage provider"), - // }, nil - // } - - // grantRes, err := c.AddGrant(ctx, grantReq) - // if err != nil { - // return nil, errors.Wrap(err, "gateway: error calling AddGrant") - // } - // if grantRes.Status.Code != rpc.Code_CODE_OK { - // return &link.CreatePublicShareResponse{ - // Status: status.NewInternal(ctx, status.NewErrorFromCode(grantRes.Status.Code, "gateway"), - // "error committing share to storage grant"), - // }, nil - // } - // } - - // TODO(refs) commit to storage if configured + // WIP store the grant in memory, as a proof of concept. + grants[res.Share.Token] = req.Grant + return res, nil } @@ -125,11 +78,30 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar }, nil } - return pClient.GetPublicShareByToken(ctx, req) + pass := string(req.Opaque.GetMap()["password"].GetValue()) + res, err := pClient.GetPublicShareByToken(ctx, req) + if err != nil { + fmt.Printf("\n\nfailed at pClient.GetPublicShareByToken\n\n") + return nil, err + } + + if req.Opaque.GetMap()["source"] != nil { + v := string(req.Opaque.GetMap()["source"].Value) + if v == "internal" { + // Filthy hack. I cannot find a way around using the gateway from the public shares storage, + // so requests coming from the storage are flagged as internal and hence skipping the password check. + return res, nil + } + } + + if res.Share.PasswordProtected && (grants[req.Token].Password != pass) { + return nil, fmt.Errorf("public share password missmatch") + } + + return res, nil } func (s *svc) GetPublicShare(ctx context.Context, req *link.GetPublicShareRequest) (*link.GetPublicShareResponse, error) { - // TODO if the date is expired DO NOT return log := appctx.GetLogger(ctx) log.Info().Msg("get public share") diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 3ce7eb9f18..512136a11c 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -27,6 +27,7 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/mitchellh/mapstructure" @@ -58,7 +59,10 @@ func (s *service) Close() error { return nil } -func (s *service) UnprotectedEndpoints() []string { return []string{} } +func (s *service) UnprotectedEndpoints() []string { + // return []string{"/cs3.sharing.link.v1beta1.LinkAPI/GetPublicShareByToken"} + return []string{} +} func (s *service) Register(ss *grpc.Server) { provider.RegisterProviderAPIServer(ss, s) @@ -304,7 +308,16 @@ func (s *service) trimMountPrefix(fn string) (string, error) { func (s *service) pathFromToken(ctx context.Context, token string) (string, error) { publicShareResponse, err := s.gateway.GetPublicShareByToken( ctx, - &link.GetPublicShareByTokenRequest{Token: token}, + &link.GetPublicShareByTokenRequest{ + Token: token, + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "source": { + Value: []byte("internal"), + }, + }, + }, + }, ) if err != nil { return "", err diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 879a9fd66c..7360dde1ac 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -24,6 +24,7 @@ import ( "path" gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" tokenpkg "github.com/cs3org/reva/pkg/token" @@ -72,29 +73,25 @@ func (h *DavHandler) Handler(s *svc) http.Handler { switch head { case "avatars": - // the avatars endpoint does not need a href prop ... yet h.AvatarsHandler.Handler(s).ServeHTTP(w, r) case "files": - // to build correct href prop urls we need to keep track of the base path base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "files") ctx := context.WithValue(ctx, ctxKeyBaseURI, base) r = r.WithContext(ctx) h.FilesHandler.Handler(s).ServeHTTP(w, r) case "meta": - // to build correct href prop urls we need to keep track of the base path base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "meta") ctx = context.WithValue(ctx, ctxKeyBaseURI, base) r = r.WithContext(ctx) h.MetaHandler.Handler(s).ServeHTTP(w, r) case "trash-bin": - // to build correct href prop urls we need to keep track of the base path base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "trash-bin") ctx := context.WithValue(ctx, ctxKeyBaseURI, base) r = r.WithContext(ctx) h.TrashbinHandler.Handler(s).ServeHTTP(w, r) case "public-files": - // TODO(refs) can this logic all be moved to the handler instead? base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "public-files") + ctx = context.WithValue(ctx, ctxKeyBaseURI, base) c, err := pool.GetGatewayServiceClient(s.c.GatewaySvc) if err != nil { w.WriteHeader(http.StatusNotFound) @@ -110,15 +107,15 @@ func (h *DavHandler) Handler(s *svc) http.Handler { } res, err := c.Authenticate(r.Context(), &authenticateRequest) - if err != nil { // TODO we might need to return not found. Do error assertion on err. + if res.Status.Code == rpcv1beta1.Code_CODE_UNAUTHENTICATED { w.WriteHeader(http.StatusUnauthorized) } - ctx := context.WithValue(ctx, ctxKeyBaseURI, base) ctx = tokenpkg.ContextSetToken(ctx, res.Token) ctx = metadata.AppendToOutgoingContext(ctx, tokenpkg.TokenHeader, res.Token) r = r.WithContext(ctx) h.PublicFilesHandler.Handler(s).ServeHTTP(w, r) + default: w.WriteHeader(http.StatusNotFound) } diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index 7b333b1496..744df26d40 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -65,7 +65,7 @@ func New(m map[string]interface{}) (auth.Manager, error) { }, nil } -func (m *manager) Authenticate(ctx context.Context, token string, secret string) (*user.User, error) { +func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user.User, error) { gwConn, err := pool.GetGatewayServiceClient(m.c.GatewayAddr) if err != nil { return nil, err @@ -75,7 +75,7 @@ func (m *manager) Authenticate(ctx context.Context, token string, secret string) Token: token, Opaque: &typesv1beta1.Opaque{ Map: map[string]*typesv1beta1.OpaqueEntry{ - "password": &typesv1beta1.OpaqueEntry{ + "password": { Value: []byte(secret), }, }, @@ -85,12 +85,6 @@ func (m *manager) Authenticate(ctx context.Context, token string, secret string) return nil, err } - // how can basic auth flow be triggered from here? - if publicShareResponse.Share.GetPasswordProtected() { - // publicShareResponse.GetShare(). - return nil, errors.New("resource password protected, bearer token not found") - } - getUserResponse, err := gwConn.GetUser(ctx, &userprovider.GetUserRequest{ UserId: publicShareResponse.GetShare().GetCreator(), }) @@ -100,3 +94,6 @@ func (m *manager) Authenticate(ctx context.Context, token string, secret string) return getUserResponse.GetUser(), nil } + +// ErrPasswordNotProvided is returned when the public share is password protected, but there was no password on the request +var ErrPasswordNotProvided = errors.New("public share is password protected, but password was not provided") From 20dfb8b8b6227fb89c4e5520282772f7e83f207d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 8 May 2020 11:52:21 +0200 Subject: [PATCH 22/43] remove spurious code --- .../storageprovider/storageprovider.go | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index e185d498ff..66c8359fd9 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -659,10 +659,6 @@ func (s *service) ListGrants(ctx context.Context, req *provider.ListGrantsReques return nil, nil } -const ( - ContextGrant = iota -) - func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) (*provider.AddGrantResponse, error) { newRef, err := s.unwrap(ctx, req.Ref) if err != nil { @@ -670,27 +666,6 @@ func (s *service) AddGrant(ctx context.Context, req *provider.AddGrantRequest) ( Status: status.NewInternal(ctx, err, "error unwrapping path"), }, nil } - // check if there is an opaque grant - // if req.GetOpaque() != nil { - // linkGrant := link.Grant{} - // val := req.GetOpaque().GetMap() - // if grantFromOpaque, ok := val["grant"]; ok { - // // TODO need to use map decoder. - // json.Unmarshal(grantFromOpaque.Value, &linkGrant) - // } - - // err := s.storage.AddGrant(ctx, newRef, nil) - // if err != nil { - // return &provider.AddGrantResponse{ - // Status: status.NewInternal(ctx, err, "error setting ACL"), - // }, nil - // } - - // res := &provider.AddGrantResponse{ - // Status: status.NewOK(ctx), - // } - // return res, nil - // } // check grantee type is valid if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_INVALID { From 8bfcc033fe1dc6d45173ec3dd06b6916a986c452 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 12 May 2020 13:49:59 +0200 Subject: [PATCH 23/43] make use of err, get rid of ineffectual assignment --- internal/http/services/owncloud/ocdav/dav.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 7360dde1ac..1cbaed68a6 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -107,6 +107,9 @@ func (h *DavHandler) Handler(s *svc) http.Handler { } res, err := c.Authenticate(r.Context(), &authenticateRequest) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } if res.Status.Code == rpcv1beta1.Code_CODE_UNAUTHENTICATED { w.WriteHeader(http.StatusUnauthorized) } From 2baa43e09f70e94251bcffb9e364538dceec6904 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 12 May 2020 14:05:23 +0200 Subject: [PATCH 24/43] run go mod tidy --- go.mod | 14 +++++++--- go.sum | 85 +++++++++++++++++++++++++++++++--------------------------- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index 952161bbda..e4421a0f47 100644 --- a/go.mod +++ b/go.mod @@ -22,26 +22,32 @@ require ( github.com/huandu/xstrings v1.3.0 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible - github.com/mattn/go-colorable v0.0.9 // indirect - github.com/mattn/go-isatty v0.0.4 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/mapstructure v1.2.2 + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/ory/fosite v0.31.0 github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect + github.com/prometheus/client_golang v0.9.3 // indirect github.com/rs/cors v1.7.0 github.com/rs/zerolog v1.18.0 go.opencensus.io v0.22.3 - golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 + golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect + golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e // indirect google.golang.org/grpc v1.29.0 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/cheggaaa/pb.v1 v1.0.27 // indirect gopkg.in/ldap.v2 v2.5.1 gopkg.in/square/go-jose.v2 v2.2.2 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index a964f13ff7..df184ea72e 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,7 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= @@ -20,21 +21,14 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzs github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.30.1 h1:cUMxtoFvIHhScZgv17tGxw15r6rVKJHR1hsIFRx9hcA= -github.com/aws/aws-sdk-go v1.30.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.30.2 h1:0vuroAsbPwVbP91MMaUmFLnrQcFBhmjQnnXaH1kcnPw= -github.com/aws/aws-sdk-go v1.30.2/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.30.3 h1:tmaR+qpBSig6RfhP9IoxALJEE1m0vfLy5tlnEIXu6WI= -github.com/aws/aws-sdk-go v1.30.3/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.30.4 h1:dpQgypC3rld2Uuz+/2u+0nbfmmyEWxau6v1hdAlvoc8= -github.com/aws/aws-sdk-go v1.30.4/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.30.7 h1:IaXfqtioP6p9SFAnNfsqdNczbR5UNbYqvcZUSsCAdTY= -github.com/aws/aws-sdk-go v1.30.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.30.12 h1:KrjyosZvkpJjcwMk0RNxMZewQ47v7+ZkbQDXjWsJMs8= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98= github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -42,16 +36,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/cs3org/go-cs3apis v0.0.0-20200324115356-e04b4fd75f03 h1:JGANezYNs/VM1Mpqu/noYqAT8HzsheysyArEaz4OnwM= -github.com/cs3org/go-cs3apis v0.0.0-20200324115356-e04b4fd75f03/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/go-cs3apis v0.0.0-20200403073321-0519c6823b48 h1:iR2JGsyZwRg6N1k9QuCJhXRH4CQUnCZNoJ0VmnjF2xE= -github.com/cs3org/go-cs3apis v0.0.0-20200403073321-0519c6823b48/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/go-cs3apis v0.0.0-20200408065125-6e23f3ecec0a h1:+enFdliTCV/aaLAvLmeka/r9wUoEypngV4JD5Gy92Uc= -github.com/cs3org/go-cs3apis v0.0.0-20200408065125-6e23f3ecec0a/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/go-cs3apis v0.0.0-20200422090600-d9e5166bebfe h1:gQgullcz2/nn1epVPhX3805nszWkSolM8m6CYLF9Y04= -github.com/cs3org/go-cs3apis v0.0.0-20200422090600-d9e5166bebfe/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/go-cs3apis v0.0.0-20200422142632-c499f9c3d1a5 h1:a7CYnlPHnjASUB1l42KANyr+7ijnMdBo4akNTT2LNyY= -github.com/cs3org/go-cs3apis v0.0.0-20200422142632-c499f9c3d1a5/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cs3org/go-cs3apis v0.0.0-20200423154403-462ce7762d4a h1:+ucCukFjYS+L7Sg3GbXoD0M0Pz6CQEhJ9HC97GHc9TU= github.com/cs3org/go-cs3apis v0.0.0-20200423154403-462ce7762d4a/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -59,6 +44,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/elazarl/goproxy v0.0.0-20181003060214-f58a169a71a5/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -68,6 +54,7 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/strfmt v0.19.2 h1:clPGfBnJohokno0e+d7hs6Yocrzjlgz6EsQSDncCRnE= @@ -120,13 +107,18 @@ github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2 github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -143,6 +135,9 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oleiade/reflections v1.0.0 h1:0ir4pc6v8/PJ0yw5AEtMddfXpWBXg9cnG7SgSoJuCgY= github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w= github.com/ory/fosite v0.31.0 h1:NZ0FA4ywPEYrCGLNVBAz2dq8vTacLDbbO4Iiy68WCKQ= @@ -166,22 +161,23 @@ github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prY github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -191,8 +187,10 @@ github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -214,8 +212,8 @@ go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -226,13 +224,14 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181003184128-c57b0facaced h1:4oqSq7eft7MdPKBGQK11X9WYUxmj6ZLgGTqYIbY1kyw= @@ -245,15 +244,21 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181021155630-eda9bb28ed51/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190415081028-16da32be82c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd h1:r7DufRZuZbWB7j439YfAzP8RPDa9unLkpwQKUYbIMPI= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= @@ -290,10 +295,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= -google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo= google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -302,6 +303,8 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzyc gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU= @@ -312,6 +315,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= From e46fb64f19c3a5fb8debcd981587a92f19d5995e Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 13 May 2020 09:42:27 +0200 Subject: [PATCH 25/43] update golangci to 1.26.0 --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index b4553abe66..c95412925d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -50,7 +50,7 @@ steps: - make ci - name: lint - image: golangci/golangci-lint:v1.21.0 + image: golangci/golangci-lint:v1.26.0 commands: - golangci-lint run From ef3549ab9462be4b92e08efc2b1edb50aff3d88b Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 13 May 2020 09:44:21 +0200 Subject: [PATCH 26/43] update golangci-lint counterpart on Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 299e5e7073..f8b5947c18 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ contrib: # for manual building only deps: - cd /tmp && rm -rf golangci-lint && git clone --quiet -b 'v1.24.0' --single-branch --depth 1 https://github.com/golangci/golangci-lint &> /dev/null && cd golangci-lint/cmd/golangci-lint && go install + cd /tmp && rm -rf golangci-lint && git clone --quiet -b 'v1.26.0' --single-branch --depth 1 https://github.com/golangci/golangci-lint &> /dev/null && cd golangci-lint/cmd/golangci-lint && go install cd /tmp && go get golang.org/x/tools/cmd/goimports build-ci: off From e0717129bbb102b581416ea71cb7d4d667f9d43d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 13 May 2020 09:51:47 +0200 Subject: [PATCH 27/43] force cache invalidation for golangci-lint --- .drone.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index c95412925d..53081fe89f 100644 --- a/.drone.yml +++ b/.drone.yml @@ -162,7 +162,8 @@ steps: - make ci - name: lint - image: golangci/golangci-lint:v1.21.0 + # will slow down build slightly. In order to get jsonpb deprecation. + image: golangci/golangci-lint:latest commands: - golangci-lint run From d918fa7519b62ef8caac11e00ce3ec1af808a238 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 14 May 2020 09:25:47 +0200 Subject: [PATCH 28/43] add user to request context, handlePropfind depends on the context user --- internal/http/services/owncloud/ocdav/dav.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index 1cbaed68a6..9bd2501231 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -28,6 +28,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/pkg/rhttp/router" tokenpkg "github.com/cs3org/reva/pkg/token" + "github.com/cs3org/reva/pkg/user" "google.golang.org/grpc/metadata" ) @@ -109,13 +110,17 @@ func (h *DavHandler) Handler(s *svc) http.Handler { res, err := c.Authenticate(r.Context(), &authenticateRequest) if err != nil { w.WriteHeader(http.StatusInternalServerError) + return } if res.Status.Code == rpcv1beta1.Code_CODE_UNAUTHENTICATED { w.WriteHeader(http.StatusUnauthorized) + return } ctx = tokenpkg.ContextSetToken(ctx, res.Token) + ctx = user.ContextSetUser(ctx, res.User) ctx = metadata.AppendToOutgoingContext(ctx, tokenpkg.TokenHeader, res.Token) + r = r.WithContext(ctx) h.PublicFilesHandler.Handler(s).ServeHTTP(w, r) From 9729151d074f24ce5cc9e87f45ec776370d33905 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 14 May 2020 13:02:37 +0200 Subject: [PATCH 29/43] use [public] share manager driver instead of the gateway, as it is an internal request --- .../services/gateway/publicshareprovider.go | 22 ++++--------------- .../publicstorageprovider.go | 16 ++++++-------- .../http/services/owncloud/ocdav/propfind.go | 2 +- pkg/auth/manager/publicshares/publicshares.go | 1 + 4 files changed, 13 insertions(+), 28 deletions(-) diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index aef9bdcba1..15ee419b4b 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -68,32 +68,18 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar log := appctx.GetLogger(ctx) log.Info().Msg("get public share by token") - pClient, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) + driver, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) if err != nil { - log.Err(err).Msg("error connecting to a public share provider") - return &link.GetPublicShareByTokenResponse{ - Status: &rpc.Status{ - Code: rpc.Code_CODE_INTERNAL, - }, - }, nil + return nil, err } + // TODO(refs) once https://github.com/cs3org/cs3apis/pull/73 is merged, password will be present in the request, not on the opaque field. pass := string(req.Opaque.GetMap()["password"].GetValue()) - res, err := pClient.GetPublicShareByToken(ctx, req) + res, err := driver.GetPublicShareByToken(ctx, req) if err != nil { - fmt.Printf("\n\nfailed at pClient.GetPublicShareByToken\n\n") return nil, err } - if req.Opaque.GetMap()["source"] != nil { - v := string(req.Opaque.GetMap()["source"].Value) - if v == "internal" { - // Filthy hack. I cannot find a way around using the gateway from the public shares storage, - // so requests coming from the storage are flagged as internal and hence skipping the password check. - return res, nil - } - } - if res.Share.PasswordProtected && (grants[req.Token].Password != pass) { return nil, fmt.Errorf("public share password missmatch") } diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index 512136a11c..b8bfb5af49 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -27,7 +27,6 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/mitchellh/mapstructure" @@ -47,6 +46,7 @@ type config struct { MountPath string `mapstructure:"mount_path"` MountID string `mapstructure:"mount_id"` GatewayAddr string `mapstructure:"gateway_addr"` + DriverAddr string `mapstructure:"driver_addr"` } type service struct { @@ -306,17 +306,15 @@ func (s *service) trimMountPrefix(fn string) (string, error) { // pathFromToken returns a reference from a public share token. func (s *service) pathFromToken(ctx context.Context, token string) (string, error) { - publicShareResponse, err := s.gateway.GetPublicShareByToken( + driver, err := pool.GetPublicShareProviderClient(s.conf.DriverAddr) + if err != nil { + return "", err + } + + publicShareResponse, err := driver.GetPublicShareByToken( ctx, &link.GetPublicShareByTokenRequest{ Token: token, - Opaque: &typesv1beta1.Opaque{ - Map: map[string]*typesv1beta1.OpaqueEntry{ - "source": { - Value: []byte("internal"), - }, - }, - }, }, ) if err != nil { diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index da2d14c955..e0bf15ddc3 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -71,7 +71,7 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) req := &provider.StatRequest{Ref: ref} res, err := client.Stat(ctx, req) if err != nil { - log.Error().Err(err).Msgf("error sending a grpc stat request to ref:%+v", ref) + log.Error().Err(err).Msgf("error sending a grpc stat request to ref: %v", ref) w.WriteHeader(http.StatusInternalServerError) return } diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index 744df26d40..840ad1eca1 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -73,6 +73,7 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user publicShareResponse, err := gwConn.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ Token: token, + // TODO replace this with the new changes on the cs3apis Opaque: &typesv1beta1.Opaque{ Map: map[string]*typesv1beta1.OpaqueEntry{ "password": { From 40ab8cba3cbbf4336f25b46c5f4ad1f5dfc11fa5 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 14 May 2020 13:06:40 +0200 Subject: [PATCH 30/43] update golangci-lint on build-onlly and build-and-publish-docker pipelines --- .drone.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 53081fe89f..1473bdce96 100644 --- a/.drone.yml +++ b/.drone.yml @@ -50,7 +50,7 @@ steps: - make ci - name: lint - image: golangci/golangci-lint:v1.26.0 + image: golangci/golangci-lint:latest commands: - golangci-lint run @@ -118,7 +118,7 @@ steps: - make ci - name: lint - image: golangci/golangci-lint:v1.21.0 + image: golangci/golangci-lint:latest commands: - golangci-lint run From 575fee75f08070db5a07b016f0d7c3da8a0de698 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 14 May 2020 13:37:27 +0200 Subject: [PATCH 31/43] ignore jsonpb on golangci.yaml --- .golangci.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.golangci.yaml b/.golangci.yaml index b7e2ed3604..03e015ef7a 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -4,6 +4,10 @@ issues: text: "SA1019:" linters: - staticcheck + - path: pkg/publicshare/manager/json/json.go + text: "SA1019:" + linters: + - staticcheck linters: enable: - bodyclose From 4cff37eb31fc3fecbc87b71a54689dc8a403df6a Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 19 May 2020 13:26:24 +0200 Subject: [PATCH 32/43] get rid of metadata-password-passing hack --- go.mod | 6 ++--- go.sum | 22 +++++++++++++++++++ .../services/gateway/publicshareprovider.go | 2 +- pkg/auth/manager/publicshares/publicshares.go | 12 ++-------- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 78ff9596a9..f8134a8ee1 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/aws/aws-sdk-go v1.30.25 github.com/cheggaaa/pb v1.0.28 github.com/coreos/go-oidc v2.2.1+incompatible - github.com/cs3org/go-cs3apis v0.0.0-20200423154403-462ce7762d4a + github.com/cs3org/go-cs3apis v0.0.0-20200515145316-7048e6a5a73d github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/eventials/go-tus v0.0.0-20190617130015-9db47421f6a0 github.com/fatih/color v1.7.0 // indirect @@ -33,14 +33,14 @@ require ( github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/client_golang v0.9.3 // indirect + github.com/prometheus/tsdb v0.7.1 // indirect github.com/rs/cors v1.7.0 github.com/rs/zerolog v1.18.0 github.com/tus/tusd v1.1.1-0.20200416115059-9deabf9d80c2 go.opencensus.io v0.22.3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect - golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 + golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e // indirect google.golang.org/grpc v1.29.0 diff --git a/go.sum b/go.sum index 0dbbf801a8..a222f00bb0 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,7 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzs github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.12 h1:KrjyosZvkpJjcwMk0RNxMZewQ47v7+ZkbQDXjWsJMs8= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.30.20 h1:ktsy2vodSZxz/arYqo7DlpkIeNohHL+4Rmjdo7YGtrE= @@ -43,6 +44,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLM github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98= @@ -55,6 +58,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cs3org/go-cs3apis v0.0.0-20200423154403-462ce7762d4a h1:+ucCukFjYS+L7Sg3GbXoD0M0Pz6CQEhJ9HC97GHc9TU= github.com/cs3org/go-cs3apis v0.0.0-20200423154403-462ce7762d4a/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20200515145316-7048e6a5a73d h1:toZvBLH1cbHT65kv6xYPd9QqwLUHwOAVHqe9j4obAq4= +github.com/cs3org/go-cs3apis v0.0.0-20200515145316-7048e6a5a73d/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -152,6 +157,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -184,6 +191,7 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -216,6 +224,8 @@ github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOi github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= @@ -225,11 +235,15 @@ github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jO github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= @@ -305,6 +319,7 @@ golang.org/x/oauth2 v0.0.0-20181003184128-c57b0facaced h1:4oqSq7eft7MdPKBGQK11X9 golang.org/x/oauth2 v0.0.0-20181003184128-c57b0facaced/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -327,6 +342,7 @@ golang.org/x/sys v0.0.0-20190415081028-16da32be82c5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd h1:r7DufRZuZbWB7j439YfAzP8RPDa9unLkpwQKUYbIMPI= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -350,6 +366,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -374,6 +391,7 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo= google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo= google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= @@ -387,9 +405,11 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= @@ -398,8 +418,10 @@ gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/h2non/gock.v1 v1.0.14/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU= gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= gopkg.in/square/go-jose.v2 v2.1.9/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 15ee419b4b..284f5d40a4 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -74,7 +74,7 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar } // TODO(refs) once https://github.com/cs3org/cs3apis/pull/73 is merged, password will be present in the request, not on the opaque field. - pass := string(req.Opaque.GetMap()["password"].GetValue()) + pass := req.GetPassword() res, err := driver.GetPublicShareByToken(ctx, req) if err != nil { return nil, err diff --git a/pkg/auth/manager/publicshares/publicshares.go b/pkg/auth/manager/publicshares/publicshares.go index 840ad1eca1..244e69877b 100644 --- a/pkg/auth/manager/publicshares/publicshares.go +++ b/pkg/auth/manager/publicshares/publicshares.go @@ -24,7 +24,6 @@ import ( user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" userprovider "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" - typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/auth" "github.com/cs3org/reva/pkg/auth/manager/registry" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" @@ -72,15 +71,8 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user } publicShareResponse, err := gwConn.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ - Token: token, - // TODO replace this with the new changes on the cs3apis - Opaque: &typesv1beta1.Opaque{ - Map: map[string]*typesv1beta1.OpaqueEntry{ - "password": { - Value: []byte(secret), - }, - }, - }, + Token: token, + Password: secret, }) if err != nil { return nil, err From 5a0a73af4a64f4512dcdd28290a690ff664f5fff Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 19 May 2020 13:56:28 +0200 Subject: [PATCH 33/43] remove comments --- internal/grpc/services/gateway/publicshareprovider.go | 1 - pkg/publicshare/publicshare.go | 1 - 2 files changed, 2 deletions(-) diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 284f5d40a4..e834fadd5c 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -73,7 +73,6 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar return nil, err } - // TODO(refs) once https://github.com/cs3org/cs3apis/pull/73 is merged, password will be present in the request, not on the opaque field. pass := req.GetPassword() res, err := driver.GetPublicShareByToken(ctx, req) if err != nil { diff --git a/pkg/publicshare/publicshare.go b/pkg/publicshare/publicshare.go index 1ae441eb65..a164e642c1 100644 --- a/pkg/publicshare/publicshare.go +++ b/pkg/publicshare/publicshare.go @@ -29,7 +29,6 @@ import ( // Manager manipulates public shares. type Manager interface { CreatePublicShare(ctx context.Context, u *user.User, md *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) - // the only place that know about which fields to update is the request: link.UpdatePublicShareRequest. This might shift to a different data structure. UpdatePublicShare(ctx context.Context, u *user.User, req *link.UpdatePublicShareRequest, g *link.Grant) (*link.PublicShare, error) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) From 9b6adc792e4ea268127021baf228a851e540b871 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 26 May 2020 10:40:01 +0200 Subject: [PATCH 34/43] use a db file for link.Grant --- internal/grpc/services/gateway/gateway.go | 5 +- .../services/gateway/publicshareprovider.go | 133 +++++++++++++++++- 2 files changed, 133 insertions(+), 5 deletions(-) diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 5b8e6b0349..4dd7a6cd97 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -57,8 +57,9 @@ type config struct { TranserExpires int64 `mapstructure:"transfer_expires"` TokenManager string `mapstructure:"token_manager"` // ShareFolder is the location where to create shares in the recipient's storage provider. - ShareFolder string `mapstructure:"share_folder"` - TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` + ShareFolder string `mapstructure:"share_folder"` + TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` + LinkGrantsFile string `mapstructure:"link_grants_file"` } type svc struct { diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index e834fadd5c..d69a2ebb27 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -19,17 +19,123 @@ package gateway import ( + "bytes" "context" + "encoding/json" "fmt" + "io/ioutil" + "os" + "sync" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/golang/protobuf/jsonpb" "github.com/pkg/errors" ) +// GrantManager is a proof of concept that allows for having persistent link grants stored +// on a map structure for convenient access. +type GrantManager struct { + lock sync.Mutex + path string // path to db file. +} + +// NewGrantManager initializes a new GrantManager. +func NewGrantManager(path string) (*GrantManager, error) { + g := GrantManager{ + lock: sync.Mutex{}, + path: path, + } + + _, err := os.Stat(g.path) + if os.IsNotExist(err) { + if err := ioutil.WriteFile(g.path, []byte("{}"), 0700); err != nil { + err = errors.Wrap(err, "error opening/creating the file: "+g.path) + return nil, err + } + } + + fileContents, err := ioutil.ReadFile(g.path) + if err != nil { + return nil, err + } + if len(fileContents) == 0 { + err := ioutil.WriteFile(g.path, []byte("{}"), 0644) + if err != nil { + return nil, err + } + } + + return &g, nil +} + +// Write writes a grant to the database. +func (g *GrantManager) Write(token string, l *link.Grant) error { + g.lock.Lock() + defer g.lock.Unlock() + + // u := jsonpb.Unmarshaler{} + m := jsonpb.Marshaler{} + + buff := bytes.Buffer{} + if err := m.Marshal(&buff, l); err != nil { + return err + } + + db := map[string]interface{}{} + fileContents, err := ioutil.ReadFile(g.path) + if err != nil { + return err + } + + if err := json.Unmarshal(fileContents, &db); err != nil { + return err + } + + if _, ok := db[token]; !ok { + db[token] = buff.String() + } else { + return errors.New("duplicated entry") + } + + destJSON, err := json.Marshal(db) + if err != nil { + return err + } + + if err := ioutil.WriteFile(g.path, destJSON, 0644); err != nil { + return err + } + + return nil +} + +// ReadFromToken gets a grant from token. +func (g *GrantManager) ReadFromToken(token string) (*link.Grant, error) { + db := map[string]interface{}{} + u := jsonpb.Unmarshaler{} + + fileContents, err := ioutil.ReadFile(g.path) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(fileContents, &db); err != nil { + return nil, err + } + + grant := link.Grant{} + r := bytes.NewBuffer([]byte(db[token].(string))) + if err := u.Unmarshal(r, &grant); err != nil { + return nil, err + } + + return &grant, nil +} + var ( // maps public share tokens to its grants. grants = map[string]*link.Grant{} @@ -39,6 +145,15 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare log := appctx.GetLogger(ctx) log.Info().Msg("create public share") + if s.c.LinkGrantsFile == "" { + return nil, fmt.Errorf("public manager used but no `link_grants_file` defined; define link_grants_file on the gateway in order to store link grants") + } + + m, err := NewGrantManager(s.c.LinkGrantsFile) + if err != nil { + return nil, err + } + c, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) if err != nil { return nil, err @@ -49,8 +164,9 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - // WIP store the grant in memory, as a proof of concept. - grants[res.Share.Token] = req.Grant + if err := m.Write(res.Share.Token, req.Grant); err != nil { + return nil, err + } return res, nil } @@ -79,7 +195,18 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar return nil, err } - if res.Share.PasswordProtected && (grants[req.Token].Password != pass) { + m, err := NewGrantManager(s.c.LinkGrantsFile) + if err != nil { + return nil, err + } + + // here + gr, err := m.ReadFromToken(req.Token) + if err != nil { + return nil, err + } + + if res.Share.PasswordProtected && (gr.Password != pass) { return nil, fmt.Errorf("public share password missmatch") } From 455e6da104435a2f41d7d3bb47a408692db6cc37 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Tue, 26 May 2020 10:42:37 +0200 Subject: [PATCH 35/43] fix linter --- .golangci.yaml | 4 ++++ go.sum | 1 + internal/grpc/services/gateway/publicshareprovider.go | 5 ----- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 03e015ef7a..6d59182f54 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -8,6 +8,10 @@ issues: text: "SA1019:" linters: - staticcheck + - path: internal/grpc/services/gateway/publicshareprovider.go + text: "SA1019:" + linters: + - staticcheck linters: enable: - bodyclose diff --git a/go.sum b/go.sum index 53bed9b163..f43f5ffe10 100644 --- a/go.sum +++ b/go.sum @@ -416,6 +416,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index d69a2ebb27..5df33c7291 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -136,11 +136,6 @@ func (g *GrantManager) ReadFromToken(token string) (*link.Grant, error) { return &grant, nil } -var ( - // maps public share tokens to its grants. - grants = map[string]*link.Grant{} -) - func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { log := appctx.GetLogger(ctx) log.Info().Msg("create public share") From 21dbf29b97a66c92e9a227dcc82c44cfaaf0987b Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 27 May 2020 11:29:06 +0200 Subject: [PATCH 36/43] fix propfind stack --- internal/http/services/owncloud/ocdav/propfind.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 06d483a079..de8525ce6e 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -99,24 +99,26 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) infos := []*provider.ResourceInfo{info} if info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER && depth != "0" { // use a stack to explore sub-containers breadth-first - stack := []string{info.Path} + stack := []*provider.ResourceInfo{info} for len(stack) > 0 { // retrieve path on top of stack - path := stack[len(stack)-1] + nextInfo := stack[len(stack)-1] ref = &provider.Reference{ - Spec: &provider.Reference_Path{Path: path}, + Spec: &provider.Reference_Id{ + Id: nextInfo.Id, + }, } req := &provider.ListContainerRequest{ Ref: ref, } res, err := client.ListContainer(ctx, req) if err != nil { - log.Error().Err(err).Str("path", path).Msg("error sending list container grpc request") + log.Error().Err(err).Str("path", nextInfo.Path).Msg("error sending list container grpc request") w.WriteHeader(http.StatusInternalServerError) return } if res.Status.Code != rpc.Code_CODE_OK { - log.Err(err).Str("path", path).Msg("error calling grpc list container") + log.Err(err).Str("path", nextInfo.Path).Msg("error calling grpc list container") w.WriteHeader(http.StatusInternalServerError) return } @@ -136,7 +138,7 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) for i := len(res.Infos) - 1; i >= 0; i-- { //for i := range res.Infos { if res.Infos[i].Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { - stack = append(stack, res.Infos[i].Path) + stack = append(stack, res.Infos[i]) } } } From a07b5797abbd4a32e065280f3cba0c4edc14a16e Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 27 May 2020 12:16:14 +0200 Subject: [PATCH 37/43] defer usage of ref --- internal/http/services/owncloud/ocdav/propfind.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index de8525ce6e..c6196f65c9 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -103,11 +103,6 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) for len(stack) > 0 { // retrieve path on top of stack nextInfo := stack[len(stack)-1] - ref = &provider.Reference{ - Spec: &provider.Reference_Id{ - Id: nextInfo.Id, - }, - } req := &provider.ListContainerRequest{ Ref: ref, } @@ -123,6 +118,12 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) return } + ref = &provider.Reference{ + Spec: &provider.Reference_Id{ + Id: nextInfo.Id, + }, + } + infos = append(infos, res.Infos...) if depth != "infinity" { From 39f3fc55bb4db152a7fa8ee9f935aed841e1f857 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 27 May 2020 17:00:12 +0200 Subject: [PATCH 38/43] Fix PROPFIND with Depth 1 Use original ref for Depth 1 which works fine. Depth infinity will have its own logic which currently only works within a single storage. --- .../http/services/owncloud/ocdav/propfind.go | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index c6196f65c9..f6d7d4423f 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -97,33 +97,48 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) info := res.Info infos := []*provider.ResourceInfo{info} - if info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER && depth != "0" { + if info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER && depth == "1" { + req := &provider.ListContainerRequest{ + Ref: ref, + } + res, err := client.ListContainer(ctx, req) + if err != nil { + log.Error().Err(err).Msg("error sending list container grpc request") + w.WriteHeader(http.StatusInternalServerError) + return + } + + if res.Status.Code != rpc.Code_CODE_OK { + log.Err(err).Msg("error calling grpc list container") + w.WriteHeader(http.StatusInternalServerError) + return + } + infos = append(infos, res.Infos...) + } else if depth == "infinity" { + // FIXME: doesn't work cross-storage as the results will have the wrong paths! // use a stack to explore sub-containers breadth-first - stack := []*provider.ResourceInfo{info} + stack := []string{info.Path} for len(stack) > 0 { // retrieve path on top of stack - nextInfo := stack[len(stack)-1] + path := stack[len(stack)-1] + ref = &provider.Reference{ + Spec: &provider.Reference_Path{Path: path}, + } req := &provider.ListContainerRequest{ Ref: ref, } res, err := client.ListContainer(ctx, req) if err != nil { - log.Error().Err(err).Str("path", nextInfo.Path).Msg("error sending list container grpc request") + log.Error().Err(err).Str("path", path).Msg("error sending list container grpc request") w.WriteHeader(http.StatusInternalServerError) return } if res.Status.Code != rpc.Code_CODE_OK { - log.Err(err).Str("path", nextInfo.Path).Msg("error calling grpc list container") + log.Err(err).Str("path", path).Msg("error calling grpc list container") w.WriteHeader(http.StatusInternalServerError) return } - ref = &provider.Reference{ - Spec: &provider.Reference_Id{ - Id: nextInfo.Id, - }, - } - infos = append(infos, res.Infos...) if depth != "infinity" { @@ -139,7 +154,7 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string) for i := len(res.Infos) - 1; i >= 0; i-- { //for i := range res.Infos { if res.Infos[i].Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { - stack = append(stack, res.Infos[i]) + stack = append(stack, res.Infos[i].Path) } } } From 68c19328da06e1f55afb89736da917498afda50a Mon Sep 17 00:00:00 2001 From: Hugo Gonzalez Labrador Date: Thu, 28 May 2020 10:17:50 +0200 Subject: [PATCH 39/43] publicshare: commit grant --- go.mod | 1 - go.sum | 4 + .../publicshareprovider.go | 2 +- pkg/publicshare/manager/json/json.go | 118 +++++++++++++++--- pkg/publicshare/publicshare.go | 2 +- 5 files changed, 110 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 7a2d2978f3..f9adb6ec8a 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/pkg/xattr v0.4.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/prometheus/tsdb v0.7.1 // indirect github.com/rs/cors v1.7.0 github.com/rs/zerolog v1.18.0 github.com/tus/tusd v1.1.1-0.20200416115059-9deabf9d80c2 diff --git a/go.sum b/go.sum index d1ab55538d..82c3531e9e 100644 --- a/go.sum +++ b/go.sum @@ -736,6 +736,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -745,6 +746,7 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFM golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -845,6 +847,7 @@ google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -903,6 +906,7 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzyc gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index 23d988d6c7..a2d97ee924 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -132,7 +132,7 @@ func (s *service) GetPublicShareByToken(ctx context.Context, req *link.GetPublic log := appctx.GetLogger(ctx) log.Info().Msg("getting public share by token") - found, err := s.sm.GetPublicShareByToken(ctx, req.GetToken()) + found, err := s.sm.GetPublicShareByToken(ctx, req.GetToken(), req.GetPassword()) if err != nil { return nil, err } diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index 9f0bd3d70b..d0bc864042 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -102,9 +102,10 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr displayName = tkn } - if len(rInfo.ArbitraryMetadata.Metadata["password"]) > 0 { - msg := "public:" + rInfo.ArbitraryMetadata.Metadata["password"] - g.Password = base64.StdEncoding.EncodeToString([]byte(msg)) + var passwordProtected bool + password := g.Password + if len(password) > 0 { + password = base64.StdEncoding.EncodeToString([]byte(password)) passwordProtected = true } @@ -132,11 +133,16 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr DisplayName: displayName, } + ps := &publicShare{ + PublicShare: s, + Password: password, + } + m.mutex.Lock() defer m.mutex.Unlock() buff := bytes.Buffer{} - if err := m.marshaler.Marshal(&buff, &s); err != nil { + if err := m.marshaler.Marshal(&buff, ps); err != nil { return nil, err } @@ -234,10 +240,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return share, nil } -// GetPublicShare gets a public share either by ID or Token. -func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *link.PublicShare, err error) { +func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *publicShare, err error) { if ref.GetToken() != "" { - share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) + share, err = m.getByToken(ctx, ref.GetToken()) if err != nil { return nil, errors.New("no shares found by token") } @@ -257,7 +262,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu } if found, ok := db[ref.GetId().GetOpaqueId()]; ok { - ps := link.PublicShare{} + ps := publicShare{} r := bytes.NewBuffer([]byte(found.(string))) if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { return nil, err @@ -269,6 +274,45 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu return } +// GetPublicShare gets a public share either by ID or Token. +func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) { + if ref.GetToken() != "" { + ps, err := m.getByToken(ctx, ref.GetToken()) + if err != nil { + return nil, errors.New("no shares found by token") + } else { + return &ps.PublicShare, nil + } + } + + m.mutex.Lock() + defer m.mutex.Unlock() + + db := map[string]interface{}{} + fileBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(fileBytes, &db); err != nil { + return nil, err + } + + found, ok := db[ref.GetId().GetOpaqueId()] + if !ok { + return nil, errors.New("no shares found by id:" + ref.GetId().String()) + } + + ps := publicShare{} + r := bytes.NewBuffer([]byte(found.(string))) + if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { + return nil, err + } + + return &ps.PublicShare, nil + +} + // ListPublicShares retrieves all the shares on the manager that are valid. func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) { shares := []*link.PublicShare{} @@ -289,13 +333,13 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] for _, v := range db { r := bytes.NewBuffer([]byte(v.(string))) - local := &link.PublicShare{} + local := &publicShare{} if err := m.unmarshaler.Unmarshal(r, local); err != nil { return nil, err } if len(filters) == 0 { - shares = append(shares, local) + shares = append(shares, &local.PublicShare) } else { for _, f := range filters { if f.Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID { @@ -305,7 +349,7 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } if local.ResourceId.StorageId == f.GetResourceId().StorageId && local.ResourceId.OpaqueId == f.GetResourceId().OpaqueId { if (local.Expiration != nil && t.After(now)) || local.Expiration == nil { - shares = append(shares, local) + shares = append(shares, &local.PublicShare) } } } @@ -321,8 +365,7 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string return fmt.Errorf("RevokePublicShare method unimplemented") } -// GetPublicShareByToken gets a public share by its opaque token. -func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { +func (m *manager) getByToken(ctx context.Context, token string) (*publicShare, error) { db := map[string]interface{}{} readBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -338,7 +381,7 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin for _, v := range db { r := bytes.NewBuffer([]byte(v.(string))) - local := &link.PublicShare{} + local := &publicShare{} if err := m.unmarshaler.Unmarshal(r, local); err != nil { return nil, err } @@ -351,6 +394,48 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*lin return nil, fmt.Errorf("share with token: `%v` not found", token) } +// GetPublicShareByToken gets a public share by its opaque token. +func (m *manager) GetPublicShareByToken(ctx context.Context, token, password string) (*link.PublicShare, error) { + db := map[string]interface{}{} + readBytes, err := ioutil.ReadFile(m.file) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(readBytes, &db); err != nil { + return nil, err + } + + m.mutex.Lock() + defer m.mutex.Unlock() + + for _, v := range db { + r := bytes.NewBuffer([]byte(v.(string))) + local := &publicShare{} + if err := m.unmarshaler.Unmarshal(r, local); err != nil { + return nil, err + } + + if local.Token == token { + // validate if it is password protected + if local.PasswordProtected { + password = base64.StdEncoding.EncodeToString([]byte(password)) + // check sent password matches stored one + if local.Password == password { + return &local.PublicShare, nil + } else { + // TODO(refs): custom permission denied error to catch up + // in uppper layers + return nil, errors.New("json: invalid password") + } + } + return &local.PublicShare, nil + } + } + + return nil, fmt.Errorf("share with token: `%v` not found", token) +} + // randString is a helper to create tokens. It could be a token manager instead. func randString(n int) string { var l = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") @@ -360,3 +445,8 @@ func randString(n int) string { } return string(b) } + +type publicShare struct { + link.PublicShare + Password string `json:"password"` +} diff --git a/pkg/publicshare/publicshare.go b/pkg/publicshare/publicshare.go index a164e642c1..fe1d9c55bb 100644 --- a/pkg/publicshare/publicshare.go +++ b/pkg/publicshare/publicshare.go @@ -33,5 +33,5 @@ type Manager interface { GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) ListPublicShares(ctx context.Context, u *user.User, filters []*link.ListPublicSharesRequest_Filter, md *provider.ResourceInfo) ([]*link.PublicShare, error) RevokePublicShare(ctx context.Context, u *user.User, id string) error - GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) + GetPublicShareByToken(ctx context.Context, token, password string) (*link.PublicShare, error) } From df39963081d52d1184ceb7b8782ab56140af78e4 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 28 May 2020 12:47:06 +0200 Subject: [PATCH 40/43] adapt db json file marshal / unmarshal --- .../services/gateway/publicshareprovider.go | 133 +----------------- .../publicshareprovider.go | 1 + .../publicstorageprovider.go | 16 ++- pkg/publicshare/manager/json/json.go | 55 ++++---- pkg/publicshare/manager/memory/memory.go | 6 +- 5 files changed, 44 insertions(+), 167 deletions(-) diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index 5df33c7291..a9e0edfb4b 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -19,123 +19,17 @@ package gateway import ( - "bytes" "context" - "encoding/json" "fmt" - "io/ioutil" - "os" - "sync" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" - "github.com/golang/protobuf/jsonpb" "github.com/pkg/errors" ) -// GrantManager is a proof of concept that allows for having persistent link grants stored -// on a map structure for convenient access. -type GrantManager struct { - lock sync.Mutex - path string // path to db file. -} - -// NewGrantManager initializes a new GrantManager. -func NewGrantManager(path string) (*GrantManager, error) { - g := GrantManager{ - lock: sync.Mutex{}, - path: path, - } - - _, err := os.Stat(g.path) - if os.IsNotExist(err) { - if err := ioutil.WriteFile(g.path, []byte("{}"), 0700); err != nil { - err = errors.Wrap(err, "error opening/creating the file: "+g.path) - return nil, err - } - } - - fileContents, err := ioutil.ReadFile(g.path) - if err != nil { - return nil, err - } - if len(fileContents) == 0 { - err := ioutil.WriteFile(g.path, []byte("{}"), 0644) - if err != nil { - return nil, err - } - } - - return &g, nil -} - -// Write writes a grant to the database. -func (g *GrantManager) Write(token string, l *link.Grant) error { - g.lock.Lock() - defer g.lock.Unlock() - - // u := jsonpb.Unmarshaler{} - m := jsonpb.Marshaler{} - - buff := bytes.Buffer{} - if err := m.Marshal(&buff, l); err != nil { - return err - } - - db := map[string]interface{}{} - fileContents, err := ioutil.ReadFile(g.path) - if err != nil { - return err - } - - if err := json.Unmarshal(fileContents, &db); err != nil { - return err - } - - if _, ok := db[token]; !ok { - db[token] = buff.String() - } else { - return errors.New("duplicated entry") - } - - destJSON, err := json.Marshal(db) - if err != nil { - return err - } - - if err := ioutil.WriteFile(g.path, destJSON, 0644); err != nil { - return err - } - - return nil -} - -// ReadFromToken gets a grant from token. -func (g *GrantManager) ReadFromToken(token string) (*link.Grant, error) { - db := map[string]interface{}{} - u := jsonpb.Unmarshaler{} - - fileContents, err := ioutil.ReadFile(g.path) - if err != nil { - return nil, err - } - - if err := json.Unmarshal(fileContents, &db); err != nil { - return nil, err - } - - grant := link.Grant{} - r := bytes.NewBuffer([]byte(db[token].(string))) - if err := u.Unmarshal(r, &grant); err != nil { - return nil, err - } - - return &grant, nil -} - func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShareRequest) (*link.CreatePublicShareResponse, error) { log := appctx.GetLogger(ctx) log.Info().Msg("create public share") @@ -143,12 +37,6 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare if s.c.LinkGrantsFile == "" { return nil, fmt.Errorf("public manager used but no `link_grants_file` defined; define link_grants_file on the gateway in order to store link grants") } - - m, err := NewGrantManager(s.c.LinkGrantsFile) - if err != nil { - return nil, err - } - c, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) if err != nil { return nil, err @@ -159,10 +47,6 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - if err := m.Write(res.Share.Token, req.Grant); err != nil { - return nil, err - } - return res, nil } @@ -184,27 +68,12 @@ func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShar return nil, err } - pass := req.GetPassword() + // TODO the double call is not here res, err := driver.GetPublicShareByToken(ctx, req) if err != nil { return nil, err } - m, err := NewGrantManager(s.c.LinkGrantsFile) - if err != nil { - return nil, err - } - - // here - gr, err := m.ReadFromToken(req.Token) - if err != nil { - return nil, err - } - - if res.Share.PasswordProtected && (gr.Password != pass) { - return nil, fmt.Errorf("public share password missmatch") - } - return res, nil } diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index a2d97ee924..7f5e40fd4b 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -132,6 +132,7 @@ func (s *service) GetPublicShareByToken(ctx context.Context, req *link.GetPublic log := appctx.GetLogger(ctx) log.Info().Msg("getting public share by token") + // there are 2 passes here, and the second request has no password found, err := s.sm.GetPublicShareByToken(ctx, req.GetToken(), req.GetPassword()) if err != nil { return nil, err diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index b8bfb5af49..fa96b7d28f 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -155,7 +155,7 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide return nil, err } - pathFromToken, err := s.pathFromToken(ctx, tkn) + pathFromToken, err := s.pathFromToken(ctx, tkn, "") if err != nil { return nil, err } @@ -196,7 +196,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer return nil, err } - pathFromToken, err := s.pathFromToken(ctx, tkn) + pathFromToken, err := s.pathFromToken(ctx, tkn, "") if err != nil { return nil, err } @@ -305,16 +305,20 @@ func (s *service) trimMountPrefix(fn string) (string, error) { } // pathFromToken returns a reference from a public share token. -func (s *service) pathFromToken(ctx context.Context, token string) (string, error) { +func (s *service) pathFromToken(ctx context.Context, token string, password string) (string, error) { driver, err := pool.GetPublicShareProviderClient(s.conf.DriverAddr) if err != nil { return "", err } - publicShareResponse, err := driver.GetPublicShareByToken( + publicShareResponse, err := driver.GetPublicShare( ctx, - &link.GetPublicShareByTokenRequest{ - Token: token, + &link.GetPublicShareRequest{ + Ref: &link.PublicShareReference{ + Spec: &link.PublicShareReference_Token{ + Token: token, + }, + }, }, ) if err != nil { diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index d0bc864042..aacf3f30ee 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -141,8 +141,8 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr m.mutex.Lock() defer m.mutex.Unlock() - buff := bytes.Buffer{} - if err := m.marshaler.Marshal(&buff, ps); err != nil { + encShare := bytes.Buffer{} + if err := m.marshaler.Marshal(&encShare, &ps.PublicShare); err != nil { return nil, err } @@ -157,7 +157,10 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr } if _, ok := db[s.Id.GetOpaqueId()]; !ok { - db[s.Id.GetOpaqueId()] = buff.String() + db[s.Id.GetOpaqueId()] = map[string]interface{}{ + "share": string(encShare.Bytes()), + "password": ps.Password, + } } else { return nil, errors.New("key already exists") } @@ -240,12 +243,13 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return share, nil } -func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (share *publicShare, err error) { +func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) { if ref.GetToken() != "" { - share, err = m.getByToken(ctx, ref.GetToken()) + share, err := m.getByToken(ctx, ref.GetToken()) if err != nil { return nil, errors.New("no shares found by token") } + return share, nil } m.mutex.Lock() @@ -261,9 +265,9 @@ func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicSh return nil, err } - if found, ok := db[ref.GetId().GetOpaqueId()]; ok { - ps := publicShare{} - r := bytes.NewBuffer([]byte(found.(string))) + if found, ok := db[ref.GetId().GetOpaqueId()].(map[string]string)["share"]; ok { + ps := link.PublicShare{} + r := bytes.NewBuffer([]byte(found)) if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { return nil, err } @@ -271,7 +275,7 @@ func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicSh return &ps, nil } - return + return nil, errors.New("no shares found") } // GetPublicShare gets a public share either by ID or Token. @@ -280,9 +284,8 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu ps, err := m.getByToken(ctx, ref.GetToken()) if err != nil { return nil, errors.New("no shares found by token") - } else { - return &ps.PublicShare, nil } + return ps, nil } m.mutex.Lock() @@ -298,7 +301,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu return nil, err } - found, ok := db[ref.GetId().GetOpaqueId()] + found, ok := db[ref.GetId().GetOpaqueId()].(map[string]interface{})["share"] if !ok { return nil, errors.New("no shares found by id:" + ref.GetId().String()) } @@ -332,9 +335,9 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } for _, v := range db { - r := bytes.NewBuffer([]byte(v.(string))) + r := bytes.NewBuffer([]byte(v.(map[string]interface{})["share"].(string))) local := &publicShare{} - if err := m.unmarshaler.Unmarshal(r, local); err != nil { + if err := m.unmarshaler.Unmarshal(r, &local.PublicShare); err != nil { return nil, err } @@ -365,7 +368,7 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string return fmt.Errorf("RevokePublicShare method unimplemented") } -func (m *manager) getByToken(ctx context.Context, token string) (*publicShare, error) { +func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicShare, error) { db := map[string]interface{}{} readBytes, err := ioutil.ReadFile(m.file) if err != nil { @@ -380,8 +383,8 @@ func (m *manager) getByToken(ctx context.Context, token string) (*publicShare, e defer m.mutex.Unlock() for _, v := range db { - r := bytes.NewBuffer([]byte(v.(string))) - local := &publicShare{} + r := bytes.NewBuffer([]byte(v.(map[string]interface{})["share"].(string))) + local := &link.PublicShare{} if err := m.unmarshaler.Unmarshal(r, local); err != nil { return nil, err } @@ -410,8 +413,9 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token, password str defer m.mutex.Unlock() for _, v := range db { - r := bytes.NewBuffer([]byte(v.(string))) - local := &publicShare{} + r := bytes.NewBuffer([]byte(v.(map[string]interface{})["share"].(string))) + passDB := v.(map[string]interface{})["password"].(string) + local := &link.PublicShare{} if err := m.unmarshaler.Unmarshal(r, local); err != nil { return nil, err } @@ -421,15 +425,14 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token, password str if local.PasswordProtected { password = base64.StdEncoding.EncodeToString([]byte(password)) // check sent password matches stored one - if local.Password == password { - return &local.PublicShare, nil - } else { - // TODO(refs): custom permission denied error to catch up - // in uppper layers - return nil, errors.New("json: invalid password") + if passDB == password { + return local, nil } + // TODO(refs): custom permission denied error to catch up + // in uppper layers + return nil, errors.New("json: invalid password") } - return &local.PublicShare, nil + return local, nil } } diff --git a/pkg/publicshare/manager/memory/memory.go b/pkg/publicshare/manager/memory/memory.go index d1968ad14d..307177a653 100644 --- a/pkg/publicshare/manager/memory/memory.go +++ b/pkg/publicshare/manager/memory/memory.go @@ -148,7 +148,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu // Attempt to fetch public share by token if ref.GetToken() != "" { - share, err = m.GetPublicShareByToken(ctx, ref.GetToken()) + share, err = m.GetPublicShareByToken(ctx, ref.GetToken(), "") if err != nil { return nil, errors.New("no shares found by token") } @@ -189,14 +189,14 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, id string) (err error) { // check whether the referente exists - if _, err := m.GetPublicShareByToken(ctx, id); err != nil { + if _, err := m.GetPublicShareByToken(ctx, id, ""); err != nil { return errors.New("reference does not exist") } m.shares.Delete(id) return } -func (m *manager) GetPublicShareByToken(ctx context.Context, token string) (*link.PublicShare, error) { +func (m *manager) GetPublicShareByToken(ctx context.Context, token string, password string) (*link.PublicShare, error) { if ps, ok := m.shares.Load(token); ok { return ps.(*link.PublicShare), nil } From d6eaa1cf6c2c12cf203b58d95abfe85dbe279d46 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 28 May 2020 12:55:03 +0200 Subject: [PATCH 41/43] remove deadcode --- pkg/publicshare/manager/json/json.go | 41 +--------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/pkg/publicshare/manager/json/json.go b/pkg/publicshare/manager/json/json.go index aacf3f30ee..17444a1237 100644 --- a/pkg/publicshare/manager/json/json.go +++ b/pkg/publicshare/manager/json/json.go @@ -84,10 +84,6 @@ type manager struct { unmarshaler jsonpb.Unmarshaler } -var ( - passwordProtected bool -) - // CreatePublicShare adds a new entry to manager.shares func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *provider.ResourceInfo, g *link.Grant) (*link.PublicShare, error) { id := &link.PublicShareId{ @@ -158,7 +154,7 @@ func (m *manager) CreatePublicShare(ctx context.Context, u *user.User, rInfo *pr if _, ok := db[s.Id.GetOpaqueId()]; !ok { db[s.Id.GetOpaqueId()] = map[string]interface{}{ - "share": string(encShare.Bytes()), + "share": encShare.String(), "password": ps.Password, } } else { @@ -243,41 +239,6 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link return share, nil } -func (m *manager) getShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) { - if ref.GetToken() != "" { - share, err := m.getByToken(ctx, ref.GetToken()) - if err != nil { - return nil, errors.New("no shares found by token") - } - return share, nil - } - - m.mutex.Lock() - defer m.mutex.Unlock() - - db := map[string]interface{}{} - fileBytes, err := ioutil.ReadFile(m.file) - if err != nil { - return nil, err - } - - if err := json.Unmarshal(fileBytes, &db); err != nil { - return nil, err - } - - if found, ok := db[ref.GetId().GetOpaqueId()].(map[string]string)["share"]; ok { - ps := link.PublicShare{} - r := bytes.NewBuffer([]byte(found)) - if err := m.unmarshaler.Unmarshal(r, &ps); err != nil { - return nil, err - } - - return &ps, nil - } - - return nil, errors.New("no shares found") -} - // GetPublicShare gets a public share either by ID or Token. func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) (*link.PublicShare, error) { if ref.GetToken() != "" { From 91bf637dd46464e9640a524068e94e5c9f674979 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 28 May 2020 12:59:05 +0200 Subject: [PATCH 42/43] remove yet more dead code --- .../services/publicstorageprovider/publicstorageprovider.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index fa96b7d28f..ef4eae2bbf 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -155,7 +155,7 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide return nil, err } - pathFromToken, err := s.pathFromToken(ctx, tkn, "") + pathFromToken, err := s.pathFromToken(ctx, tkn) if err != nil { return nil, err } @@ -196,7 +196,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer return nil, err } - pathFromToken, err := s.pathFromToken(ctx, tkn, "") + pathFromToken, err := s.pathFromToken(ctx, tkn) if err != nil { return nil, err } @@ -305,7 +305,7 @@ func (s *service) trimMountPrefix(fn string) (string, error) { } // pathFromToken returns a reference from a public share token. -func (s *service) pathFromToken(ctx context.Context, token string, password string) (string, error) { +func (s *service) pathFromToken(ctx context.Context, token string) (string, error) { driver, err := pool.GetPublicShareProviderClient(s.conf.DriverAddr) if err != nil { return "", err From e42564b8936542fbbe909f83088bcb540d0d117f Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 28 May 2020 13:01:08 +0200 Subject: [PATCH 43/43] remove unused config parameter --- internal/grpc/services/gateway/gateway.go | 5 ++--- internal/grpc/services/gateway/publicshareprovider.go | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/internal/grpc/services/gateway/gateway.go b/internal/grpc/services/gateway/gateway.go index 4dd7a6cd97..5b8e6b0349 100644 --- a/internal/grpc/services/gateway/gateway.go +++ b/internal/grpc/services/gateway/gateway.go @@ -57,9 +57,8 @@ type config struct { TranserExpires int64 `mapstructure:"transfer_expires"` TokenManager string `mapstructure:"token_manager"` // ShareFolder is the location where to create shares in the recipient's storage provider. - ShareFolder string `mapstructure:"share_folder"` - TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` - LinkGrantsFile string `mapstructure:"link_grants_file"` + ShareFolder string `mapstructure:"share_folder"` + TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` } type svc struct { diff --git a/internal/grpc/services/gateway/publicshareprovider.go b/internal/grpc/services/gateway/publicshareprovider.go index a9e0edfb4b..d2fab6ff76 100644 --- a/internal/grpc/services/gateway/publicshareprovider.go +++ b/internal/grpc/services/gateway/publicshareprovider.go @@ -20,7 +20,6 @@ package gateway import ( "context" - "fmt" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" @@ -34,9 +33,6 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare log := appctx.GetLogger(ctx) log.Info().Msg("create public share") - if s.c.LinkGrantsFile == "" { - return nil, fmt.Errorf("public manager used but no `link_grants_file` defined; define link_grants_file on the gateway in order to store link grants") - } c, err := pool.GetPublicShareProviderClient(s.c.PublicShareProviderEndpoint) if err != nil { return nil, err