Skip to content

Commit

Permalink
List OCM valid invite tokens (#3665)
Browse files Browse the repository at this point in the history
* boilerplate code for listing tokens

* implements list token in all token repositories

* add endpoint in sciencemesh http service to list invite tokens

* add changelog

* update go-cs3apis

* fix tests
  • Loading branch information
gmgigi96 committed Feb 21, 2023
1 parent 7e4ce31 commit d023f6c
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 3 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/ocm-invite-list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: List valid OCM invite tokens

Adds the endpoint `/list-invite` in the sciencemesh service,
to get the list of valid OCM invite tokens.

https://github.com/cs3org/reva/pull/3665
https://github.com/cs3org/cs3apis/pull/201
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/cheggaaa/pb v1.0.29
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e
github.com/cs3org/go-cs3apis v0.0.0-20230214162720-ac2ceb2ad50e
github.com/cs3org/go-cs3apis v0.0.0-20230220105024-9b045290a172
github.com/dgraph-io/ristretto v0.1.1
github.com/dolthub/go-mysql-server v0.14.0
github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJff
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/go-cs3apis v0.0.0-20230214162720-ac2ceb2ad50e h1:w4A601AS6pC+3eHb9XDZe5Ctpi4cFyoFnsed2Yisd8Q=
github.com/cs3org/go-cs3apis v0.0.0-20230214162720-ac2ceb2ad50e/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20230220105024-9b045290a172 h1:S2WbxNSNhrrQGIlvfNkMAmekcQtINvmU51gsKFZEKPo=
github.com/cs3org/go-cs3apis v0.0.0-20230220105024-9b045290a172/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
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=
Expand Down
16 changes: 16 additions & 0 deletions internal/grpc/services/gateway/ocminvitemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ func (s *svc) GenerateInviteToken(ctx context.Context, req *invitepb.GenerateInv
return res, nil
}

func (s *svc) ListInviteTokens(ctx context.Context, req *invitepb.ListInviteTokensRequest) (*invitepb.ListInviteTokensResponse, error) {
c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint))
if err != nil {
return &invitepb.ListInviteTokensResponse{
Status: status.NewInternal(ctx, err, "error getting user invite provider client"),
}, nil
}

res, err := c.ListInviteTokens(ctx, req)
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling ListInviteTokens")
}

return res, nil
}

func (s *svc) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequest) (*invitepb.ForwardInviteResponse, error) {
c, err := pool.GetOCMInviteManagerClient(pool.Endpoint(s.c.OCMInviteManagerEndpoint))
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions internal/grpc/services/ocminvitemanager/ocminvitemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ func (s *service) GenerateInviteToken(ctx context.Context, req *invitepb.Generat
}, nil
}

func (s *service) ListInviteTokens(ctx context.Context, req *invitepb.ListInviteTokensRequest) (*invitepb.ListInviteTokensResponse, error) {
user := ctxpkg.ContextMustGetUser(ctx)
tokens, err := s.repo.ListTokens(ctx, user.Id)
if err != nil {
return &invitepb.ListInviteTokensResponse{
Status: status.NewInternal(ctx, err, "error listing tokens"),
}, nil
}
return &invitepb.ListInviteTokensResponse{
Status: status.NewOK(ctx),
InviteTokens: tokens,
}, nil
}

func (s *service) ForwardInvite(ctx context.Context, req *invitepb.ForwardInviteRequest) (*invitepb.ForwardInviteResponse, error) {
user := ctxpkg.ContextMustGetUser(ctx)

Expand Down
21 changes: 20 additions & 1 deletion internal/http/services/ocmd/protocols_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,32 @@ func TestUnmarshalProtocol(t *testing.T) {
}

if tt.err == "" {
if !reflect.DeepEqual(got, tt.expected) {
if !protocolsEqual(got, tt.expected) {
t.Fatalf("result does not match with expected. got=%+v expected=%+v", render.AsCode(got), render.AsCode(tt.expected))
}
}
}
}

func protocolsToMap(p Protocols) map[string]Protocol {
m := make(map[string]Protocol)
for _, prot := range p {
switch prot.(type) {
case *WebDAV:
m["webdav"] = prot
case *Webapp:
m["webapp"] = prot
case *Datatx:
m["datatx"] = prot
}
}
return m
}

func protocolsEqual(p1, p2 Protocols) bool {
return reflect.DeepEqual(protocolsToMap(p1), protocolsToMap(p2))
}

func TestMarshalProtocol(t *testing.T) {
tests := []struct {
in Protocols
Expand Down
1 change: 1 addition & 0 deletions internal/http/services/sciencemesh/sciencemesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (s *svc) routerInit() error {
}

s.router.Get("/generate-invite", tokenHandler.Generate)
s.router.Get("/list-invite", tokenHandler.ListInvite)
s.router.Post("/accept-invite", tokenHandler.AcceptInvite)
s.router.Get("/find-accepted-users", tokenHandler.FindAccepted)

Expand Down
23 changes: 23 additions & 0 deletions internal/http/services/sciencemesh/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,26 @@ func (h *tokenHandler) FindAccepted(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}

func (h *tokenHandler) ListInvite(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

res, err := h.gatewayClient.ListInviteTokens(ctx, &invitepb.ListInviteTokensRequest{})
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error listing tokens", err)
return
}

if res.Status.Code != rpc.Code_CODE_OK {
reqres.WriteError(w, r, reqres.APIErrorServerError, res.Status.Message, errors.New(res.Status.Message))
return
}

if err := json.NewEncoder(w).Encode(res.InviteTokens); err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error marshalling token data", err)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
3 changes: 3 additions & 0 deletions pkg/ocm/invite/invite.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Repository interface {
// GetToken gets the token from the repository.
GetToken(ctx context.Context, token string) (*invitepb.InviteToken, error)

// ListTokens gets the valid tokens from the repository (i.e. not expired).
ListTokens(ctx context.Context, initiator *userpb.UserId) ([]*invitepb.InviteToken, error)

// AddRemoteUser stores the remote user.
AddRemoteUser(ctx context.Context, initiator *userpb.UserId, remoteUser *userpb.User) error

Expand Down
14 changes: 14 additions & 0 deletions pkg/ocm/invite/repository/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/ocm/invite"
"github.com/cs3org/reva/pkg/ocm/invite/repository/registry"
"github.com/cs3org/reva/pkg/utils"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -166,6 +167,19 @@ func (m *manager) GetToken(ctx context.Context, token string) (*invitepb.InviteT
return nil, invite.ErrTokenNotFound
}

func (m *manager) ListTokens(ctx context.Context, initiator *userpb.UserId) ([]*invitepb.InviteToken, error) {
m.RLock()
defer m.RUnlock()

tokens := []*invitepb.InviteToken{}
for _, token := range m.model.Invites {
if utils.UserEqual(token.UserId, initiator) {
tokens = append(tokens, token)
}
}
return tokens, nil
}

func (m *manager) AddRemoteUser(ctx context.Context, initiator *userpb.UserId, remoteUser *userpb.User) error {
m.Lock()
defer m.Unlock()
Expand Down
13 changes: 13 additions & 0 deletions pkg/ocm/invite/repository/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/ocm/invite"
"github.com/cs3org/reva/pkg/ocm/invite/repository/registry"
"github.com/cs3org/reva/pkg/utils"
)

func init() {
Expand Down Expand Up @@ -59,6 +60,18 @@ func (m *manager) GetToken(ctx context.Context, token string) (*invitepb.InviteT
return nil, invite.ErrTokenNotFound
}

func (m *manager) ListTokens(ctx context.Context, initiator *userpb.UserId) ([]*invitepb.InviteToken, error) {
tokens := []*invitepb.InviteToken{}
m.Invites.Range(func(_, value any) bool {
token := value.(*invitepb.InviteToken)
if utils.UserEqual(token.UserId, initiator) {
tokens = append(tokens, token)
}
return true
})
return tokens, nil
}

func (m *manager) AddRemoteUser(ctx context.Context, initiator *userpb.UserId, remoteUser *userpb.User) error {
usersList, ok := m.AcceptedUsers.Load(initiator)
acceptedUsers := usersList.([]*userpb.User)
Expand Down
26 changes: 25 additions & 1 deletion pkg/ocm/invite/repository/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,38 @@ func (m *mgr) GetToken(ctx context.Context, token string) (*invitepb.InviteToken
}
return nil, err
}
return convertToInviteToken(tkn), nil
}

func convertToInviteToken(tkn dbToken) *invitepb.InviteToken {
return &invitepb.InviteToken{
Token: tkn.Token,
UserId: conversions.ExtractUserID(tkn.Initiator),
Expiration: &types.Timestamp{
Seconds: uint64(tkn.Expiration.Unix()),
},
Description: tkn.Description,
}, nil
}
}

func (m *mgr) ListTokens(ctx context.Context, initiator *userpb.UserId) ([]*invitepb.InviteToken, error) {
query := "SELECT token, initiator, expiration, description FROM ocm_tokens WHERE initiator=?"

tokens := []*invitepb.InviteToken{}
rows, err := m.db.QueryContext(ctx, query, conversions.FormatUserID(initiator))
if err != nil {
return nil, err
}

var tkn dbToken
for rows.Next() {
if err := rows.Scan(&tkn.Token, &tkn.Initiator, &tkn.Expiration, &tkn.Description); err != nil {
continue
}
tokens = append(tokens, convertToInviteToken(tkn))
}

return tokens, nil
}

// AddRemoteUser stores the remote user.
Expand Down

0 comments on commit d023f6c

Please sign in to comment.