Skip to content

Commit

Permalink
feat(grant): introduce update grant API (raystack#374)
Browse files Browse the repository at this point in the history
* feat(grant): introduce update grant API

* feat(grant): send notification to previous and new owner when owner is updated
  • Loading branch information
rahmatrhd authored Mar 10, 2023
1 parent 8937f4a commit 975f5cb
Show file tree
Hide file tree
Showing 14 changed files with 1,845 additions and 1,186 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ COMMIT := $(shell git rev-parse --short HEAD)
TAG := "$(shell git rev-list --tags --max-count=1)"
VERSION := "$(shell git describe --tags ${TAG})-next"
BUILD_DIR=dist
PROTON_COMMIT := "912d3124486acfc44310d92e15169b41a2f5f0ef"
PROTON_COMMIT := "b9b0deda4ba141084b1741805a1682e26e2a2e74"

.PHONY: all build clean test tidy vet proto setup format generate

Expand Down
26 changes: 26 additions & 0 deletions api/handler/v1beta1/grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,32 @@ func (s *GRPCServer) RevokeGrant(ctx context.Context, req *guardianv1beta1.Revok
}, nil
}

func (s *GRPCServer) UpdateGrant(ctx context.Context, req *guardianv1beta1.UpdateGrantRequest) (*guardianv1beta1.UpdateGrantResponse, error) {
g := &domain.Grant{
ID: req.GetId(),
Owner: req.GetOwner(),
}
if err := s.grantService.Update(ctx, g); err != nil {
switch {
case errors.Is(err, grant.ErrGrantNotFound):
return nil, status.Error(codes.NotFound, err.Error())
case errors.Is(err, grant.ErrEmptyOwner):
return nil, status.Error(codes.InvalidArgument, err.Error())
default:
return nil, status.Errorf(codes.Internal, "failed to update grant: %v", err)
}
}

grantProto, err := s.adapter.ToGrantProto(g)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to parse grant: %v", err)
}

return &guardianv1beta1.UpdateGrantResponse{
Grant: grantProto,
}, nil
}

func (s *GRPCServer) RevokeGrants(ctx context.Context, req *guardianv1beta1.RevokeGrantsRequest) (*guardianv1beta1.RevokeGrantsResponse, error) {
actor, err := s.getUser(ctx)
if err != nil {
Expand Down
73 changes: 73 additions & 0 deletions api/handler/v1beta1/grant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,79 @@ func (s *GrpcHandlersSuite) TestGetGrant() {
})
}

func (s *GrpcHandlersSuite) TestUpdateGrant() {
s.Run("should return grant details on succes", func() {
s.setup()

expectedGrant := &domain.Grant{
ID: "test-id",
Owner: "test-owner",
}
now := time.Now()
s.grantService.EXPECT().
Update(mock.AnythingOfType("*context.emptyCtx"), expectedGrant).
Run(func(_a0 context.Context, g *domain.Grant) {
g.UpdatedAt = now
}).
Return(nil).Once()

req := &guardianv1beta1.UpdateGrantRequest{
Id: "test-id",
Owner: "test-owner",
}
res, err := s.grpcServer.UpdateGrant(context.Background(), req)

s.NoError(err)
s.Equal(expectedGrant.ID, res.Grant.Id)
s.Equal(expectedGrant.Owner, res.Grant.Owner)
s.Equal(timestamppb.New(now), res.Grant.UpdatedAt)
})

s.Run("should return error if grant service returns an error", func() {
testCases := []struct {
name string
expectedError error
expectedCode codes.Code
}{
{
"should return not found error if record not found",
grant.ErrGrantNotFound,
codes.NotFound,
},
{
"should return invalid argument error if owner is empty",
grant.ErrEmptyOwner,
codes.InvalidArgument,
},
{
"should return internal error if there's an unexpected error",
errors.New("unexpected error"),
codes.Internal,
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
s.setup()

s.grantService.EXPECT().
Update(mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("*domain.Grant")).
Return(tc.expectedError).Once()

req := &guardianv1beta1.UpdateGrantRequest{
Id: "test-id",
Owner: "test-owner",
}
res, err := s.grpcServer.UpdateGrant(context.Background(), req)

s.Equal(tc.expectedCode, status.Code(err))
s.Nil(res)
s.grantService.AssertExpectations(s.T())
})
}
})
}

func (s *GrpcHandlersSuite) TestImportFromProvider() {
s.Run("should return grants on success", func() {
s.setup()
Expand Down
1 change: 1 addition & 0 deletions api/handler/v1beta1/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ type approvalService interface {
type grantService interface {
List(context.Context, domain.ListGrantsFilter) ([]domain.Grant, error)
GetByID(context.Context, string) (*domain.Grant, error)
Update(context.Context, *domain.Grant) error
Revoke(ctx context.Context, id, actor, reason string, opts ...grant.Option) (*domain.Grant, error)
BulkRevoke(ctx context.Context, filter domain.RevokeGrantsFilter, actor, reason string) ([]*domain.Grant, error)
ImportFromProvider(ctx context.Context, criteria grant.ImportFromProviderCriteria) ([]*domain.Grant, error)
Expand Down
Loading

0 comments on commit 975f5cb

Please sign in to comment.