Skip to content

Commit 975f5cb

Browse files
authored
feat(grant): introduce update grant API (#374)
* feat(grant): introduce update grant API * feat(grant): send notification to previous and new owner when owner is updated
1 parent 8937f4a commit 975f5cb

File tree

14 files changed

+1845
-1186
lines changed

14 files changed

+1845
-1186
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ COMMIT := $(shell git rev-parse --short HEAD)
33
TAG := "$(shell git rev-list --tags --max-count=1)"
44
VERSION := "$(shell git describe --tags ${TAG})-next"
55
BUILD_DIR=dist
6-
PROTON_COMMIT := "912d3124486acfc44310d92e15169b41a2f5f0ef"
6+
PROTON_COMMIT := "b9b0deda4ba141084b1741805a1682e26e2a2e74"
77

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

api/handler/v1beta1/grant.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,32 @@ func (s *GRPCServer) RevokeGrant(ctx context.Context, req *guardianv1beta1.Revok
109109
}, nil
110110
}
111111

112+
func (s *GRPCServer) UpdateGrant(ctx context.Context, req *guardianv1beta1.UpdateGrantRequest) (*guardianv1beta1.UpdateGrantResponse, error) {
113+
g := &domain.Grant{
114+
ID: req.GetId(),
115+
Owner: req.GetOwner(),
116+
}
117+
if err := s.grantService.Update(ctx, g); err != nil {
118+
switch {
119+
case errors.Is(err, grant.ErrGrantNotFound):
120+
return nil, status.Error(codes.NotFound, err.Error())
121+
case errors.Is(err, grant.ErrEmptyOwner):
122+
return nil, status.Error(codes.InvalidArgument, err.Error())
123+
default:
124+
return nil, status.Errorf(codes.Internal, "failed to update grant: %v", err)
125+
}
126+
}
127+
128+
grantProto, err := s.adapter.ToGrantProto(g)
129+
if err != nil {
130+
return nil, status.Errorf(codes.Internal, "failed to parse grant: %v", err)
131+
}
132+
133+
return &guardianv1beta1.UpdateGrantResponse{
134+
Grant: grantProto,
135+
}, nil
136+
}
137+
112138
func (s *GRPCServer) RevokeGrants(ctx context.Context, req *guardianv1beta1.RevokeGrantsRequest) (*guardianv1beta1.RevokeGrantsResponse, error) {
113139
actor, err := s.getUser(ctx)
114140
if err != nil {

api/handler/v1beta1/grant_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,79 @@ func (s *GrpcHandlersSuite) TestGetGrant() {
252252
})
253253
}
254254

255+
func (s *GrpcHandlersSuite) TestUpdateGrant() {
256+
s.Run("should return grant details on succes", func() {
257+
s.setup()
258+
259+
expectedGrant := &domain.Grant{
260+
ID: "test-id",
261+
Owner: "test-owner",
262+
}
263+
now := time.Now()
264+
s.grantService.EXPECT().
265+
Update(mock.AnythingOfType("*context.emptyCtx"), expectedGrant).
266+
Run(func(_a0 context.Context, g *domain.Grant) {
267+
g.UpdatedAt = now
268+
}).
269+
Return(nil).Once()
270+
271+
req := &guardianv1beta1.UpdateGrantRequest{
272+
Id: "test-id",
273+
Owner: "test-owner",
274+
}
275+
res, err := s.grpcServer.UpdateGrant(context.Background(), req)
276+
277+
s.NoError(err)
278+
s.Equal(expectedGrant.ID, res.Grant.Id)
279+
s.Equal(expectedGrant.Owner, res.Grant.Owner)
280+
s.Equal(timestamppb.New(now), res.Grant.UpdatedAt)
281+
})
282+
283+
s.Run("should return error if grant service returns an error", func() {
284+
testCases := []struct {
285+
name string
286+
expectedError error
287+
expectedCode codes.Code
288+
}{
289+
{
290+
"should return not found error if record not found",
291+
grant.ErrGrantNotFound,
292+
codes.NotFound,
293+
},
294+
{
295+
"should return invalid argument error if owner is empty",
296+
grant.ErrEmptyOwner,
297+
codes.InvalidArgument,
298+
},
299+
{
300+
"should return internal error if there's an unexpected error",
301+
errors.New("unexpected error"),
302+
codes.Internal,
303+
},
304+
}
305+
306+
for _, tc := range testCases {
307+
s.Run(tc.name, func() {
308+
s.setup()
309+
310+
s.grantService.EXPECT().
311+
Update(mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("*domain.Grant")).
312+
Return(tc.expectedError).Once()
313+
314+
req := &guardianv1beta1.UpdateGrantRequest{
315+
Id: "test-id",
316+
Owner: "test-owner",
317+
}
318+
res, err := s.grpcServer.UpdateGrant(context.Background(), req)
319+
320+
s.Equal(tc.expectedCode, status.Code(err))
321+
s.Nil(res)
322+
s.grantService.AssertExpectations(s.T())
323+
})
324+
}
325+
})
326+
}
327+
255328
func (s *GrpcHandlersSuite) TestImportFromProvider() {
256329
s.Run("should return grants on success", func() {
257330
s.setup()

api/handler/v1beta1/grpc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ type approvalService interface {
102102
type grantService interface {
103103
List(context.Context, domain.ListGrantsFilter) ([]domain.Grant, error)
104104
GetByID(context.Context, string) (*domain.Grant, error)
105+
Update(context.Context, *domain.Grant) error
105106
Revoke(ctx context.Context, id, actor, reason string, opts ...grant.Option) (*domain.Grant, error)
106107
BulkRevoke(ctx context.Context, filter domain.RevokeGrantsFilter, actor, reason string) ([]*domain.Grant, error)
107108
ImportFromProvider(ctx context.Context, criteria grant.ImportFromProviderCriteria) ([]*domain.Grant, error)

0 commit comments

Comments
 (0)