Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: schema generator #31

Merged
merged 60 commits into from
Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
fc94118
feat: add build_schema function
rsbh Nov 16, 2021
6f5b825
feat: add function to build policy definiton
rsbh Nov 16, 2021
38ed0f0
chore: add namespace to roles
rsbh Nov 17, 2021
4ac6e75
chore: add subtype to roles
rsbh Nov 17, 2021
20408a6
chore: add actions table
rsbh Nov 17, 2021
2cb75f6
chore: add namespaces table
rsbh Nov 17, 2021
92831b2
chore: add support for multiple role types
rsbh Nov 17, 2021
0b0fd57
feat: add build_schema function
rsbh Nov 16, 2021
2585a63
feat: add function to build policy definiton
rsbh Nov 16, 2021
e807e1f
chore: add namespace to roles
rsbh Nov 17, 2021
5208208
chore: add subtype to roles
rsbh Nov 17, 2021
31a7b5c
chore: add actions table
rsbh Nov 17, 2021
88cdb13
chore: add namespaces table
rsbh Nov 17, 2021
c5fa06d
chore: add support for multiple role types
rsbh Nov 17, 2021
76e3d44
fix: https://github.com/googleapis/go-genproto/issues/700
rsbh Nov 17, 2021
1d3e1a3
Merge branch 'schema_generator' of github.com:odpf/shield into schema…
rsbh Nov 17, 2021
c6abb6c
refactor: move schema models to model package
rsbh Nov 18, 2021
a6c2939
chore: add policies table
rsbh Nov 18, 2021
989b100
refactor: change schema generator Policy to model.Policy
rsbh Nov 19, 2021
67121bb
refactor: change struct keys to lowercase
rsbh Nov 20, 2021
b70f530
chore: add namespace_id to roles and actions
rsbh Nov 20, 2021
81e938c
refactor: remove slug from namespace and actions
rsbh Nov 21, 2021
868b1d0
chore: add check for action namespace in schema generation
rsbh Nov 21, 2021
5126eca
chore: namespace_id to actions and roles struct
rsbh Nov 21, 2021
2c7e170
fix: create roles api db error
rsbh Nov 21, 2021
2dfefa6
chore: add list policies api
rsbh Nov 21, 2021
cf2d831
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Nov 21, 2021
266cdc8
chore: register policy service
rsbh Nov 21, 2021
6cae37f
chore: add create policy api
rsbh Nov 21, 2021
95e22f4
chore: add get policy api
rsbh Nov 21, 2021
c0cd897
chore: add update policy api
rsbh Nov 21, 2021
03e9d8e
chore: add schema generator to create and update policy
rsbh Nov 21, 2021
3656c72
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Nov 29, 2021
9985eed
chore: add spicedb config and setup in docker-compose
rsbh Nov 29, 2021
df90e1f
chore: add authz package to connect to spicedb
rsbh Nov 29, 2021
5a2fcbe
chore: add authz AddPolicy Method
rsbh Dec 2, 2021
92b5aed
refactor: fix lint issues
rsbh Dec 2, 2021
82ede4e
chore: add hook to push schema to spicedb on Create and Update Policy
rsbh Dec 2, 2021
81a14e1
chore: add namespace field to roles response
rsbh Dec 3, 2021
84684fa
feat: add namespace apis
rsbh Dec 3, 2021
9a27298
feat: add actions crud apis
rsbh Dec 3, 2021
5373e7d
feat: add polices crud apis
rsbh Dec 5, 2021
17bbb80
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Dec 5, 2021
c313ae3
fix: go import lint issues
rsbh Dec 5, 2021
6e6e03c
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Dec 7, 2021
4c33d6a
chore: update proto path for shield apis
rsbh Dec 7, 2021
3d79589
chore: add shield apis proto generated files
rsbh Dec 7, 2021
4e9694a
fix: lint issues
rsbh Dec 7, 2021
9bd8c19
fix: policy tests issue
rsbh Dec 7, 2021
7ce8338
fix: schema generator tests issue
rsbh Dec 7, 2021
372918c
fix: sort definitions to fix Schema generator tests issue
rsbh Dec 7, 2021
6679fb5
fix: sort roles and actions to fix tests
rsbh Dec 7, 2021
1ecd0b1
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Dec 8, 2021
de961fa
chore: update shield proto path
rsbh Dec 8, 2021
86ba5f7
chore: cleanup unused code and logs
rsbh Dec 9, 2021
78f3e17
chore: pass context to AddPolicy
rsbh Dec 10, 2021
1ecc1d9
chore: fix typo and update polices query to take argument
rsbh Dec 10, 2021
dac8400
chore(policy): Add Update method for action and namespace
rsbh Dec 10, 2021
ee8503c
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Dec 10, 2021
d1a3246
Merge branch 'main' of github.com:odpf/shield into schema_generator
rsbh Dec 10, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion api/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ func Register(ctx context.Context, s *server.MuxServer, gw *server.GRPCGateway,

// grpc gateway api will have version endpoints
s.SetGateway("/", gw)

v1.RegisterV1(ctx, s, gw, deps.V1)
}
132 changes: 132 additions & 0 deletions api/handler/v1/action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package v1

import (
"context"
"errors"

grpczap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
"github.com/odpf/shield/internal/schema"
"github.com/odpf/shield/model"
shieldv1 "github.com/odpf/shield/proto/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)

type ActionService interface {
GetAction(ctx context.Context, id string) (model.Action, error)
ListActions(ctx context.Context) ([]model.Action, error)
CreateAction(ctx context.Context, action model.Action) (model.Action, error)
UpdateAction(ctx context.Context, id string, action model.Action) (model.Action, error)
}

var grpcActionNotFoundErr = status.Errorf(codes.NotFound, "action doesn't exist")

func (v Dep) ListActions(ctx context.Context, request *shieldv1.ListActionsRequest) (*shieldv1.ListActionsResponse, error) {
logger := grpczap.Extract(ctx)
var actions []*shieldv1.Action

actionsList, err := v.ActionService.ListActions(ctx)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

for _, act := range actionsList {
actPB, err := transformActionToPB(act)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

actions = append(actions, &actPB)
}

return &shieldv1.ListActionsResponse{Actions: actions}, nil
}

func (v Dep) CreateAction(ctx context.Context, request *shieldv1.CreateActionRequest) (*shieldv1.CreateActionResponse, error) {
logger := grpczap.Extract(ctx)

newAction, err := v.ActionService.CreateAction(ctx, model.Action{
Id: request.GetBody().Id,
Name: request.GetBody().Name,
NamespaceId: request.GetBody().NamespaceId,
})

if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

actionPB, err := transformActionToPB(newAction)

if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.CreateActionResponse{Action: &actionPB}, nil
}

func (v Dep) GetAction(ctx context.Context, request *shieldv1.GetActionRequest) (*shieldv1.GetActionResponse, error) {
logger := grpczap.Extract(ctx)

fetchedAction, err := v.ActionService.GetAction(ctx, request.GetId())
if err != nil {
logger.Error(err.Error())
switch {
case errors.Is(err, schema.ActionDoesntExist):
return nil, grpcActionNotFoundErr
case errors.Is(err, schema.InvalidUUID):
return nil, grpcBadBodyError
default:
return nil, grpcInternalServerError
}
}

actionPB, err := transformActionToPB(fetchedAction)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.GetActionResponse{Action: &actionPB}, nil
}

func (v Dep) UpdateAction(ctx context.Context, request *shieldv1.UpdateActionRequest) (*shieldv1.UpdateActionResponse, error) {
logger := grpczap.Extract(ctx)

updatedAction, err := v.ActionService.UpdateAction(ctx, request.GetId(), model.Action{
Id: request.GetId(),
Name: request.GetBody().Name,
NamespaceId: request.GetBody().NamespaceId,
})

if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

actionPB, err := transformActionToPB(updatedAction)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.UpdateActionResponse{Action: &actionPB}, nil
}

func transformActionToPB(act model.Action) (shieldv1.Action, error) {
namespace, err := transformNamespaceToPB(act.Namespace)
if err != nil {
return shieldv1.Action{}, err
}
return shieldv1.Action{
Id: act.Id,
Name: act.Name,
Namespace: &namespace,
CreatedAt: timestamppb.New(act.CreatedAt),
UpdatedAt: timestamppb.New(act.UpdatedAt),
}, nil
}
233 changes: 233 additions & 0 deletions api/handler/v1/action_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package v1

import (
"context"
"errors"
"sort"
"strings"
"testing"
"time"

"github.com/odpf/shield/model"
shieldv1 "github.com/odpf/shield/proto/v1"

"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)

var testActionMap = map[string]model.Action{
"read": {
Id: "read",
Name: "Read",
Namespace: model.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
"write": {
Id: "write",
Name: "Write",
Namespace: model.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
"manage": {
Id: "manage",
Name: "Manage",
Namespace: model.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
CreatedAt: time.Time{},
UpdatedAt: time.Time{},
},
}

func TestListActions(t *testing.T) {
t.Parallel()
table := []struct {
title string
mockActionSrc mockActionSrv
req *shieldv1.ListActionsRequest
want *shieldv1.ListActionsResponse
err error
}{
{
title: "error in Action Service",
mockActionSrc: mockActionSrv{ListActionsFunc: func(ctx context.Context) (actions []model.Action, err error) {
return []model.Action{}, errors.New("some error")
}},
want: nil,
err: status.Errorf(codes.Internal, internalServerError.Error()),
},
{
title: "success",
mockActionSrc: mockActionSrv{ListActionsFunc: func(ctx context.Context) (actions []model.Action, err error) {
var testActionList []model.Action
for _, act := range testActionMap {
testActionList = append(testActionList, act)
}

sort.Slice(testActionList[:], func(i, j int) bool {
return strings.Compare(testActionList[i].Id, testActionList[j].Id) < 1
})
return testActionList, nil
}},
want: &shieldv1.ListActionsResponse{Actions: []*shieldv1.Action{
{
Id: "manage",
Name: "Manage",
Namespace: &shieldv1.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
{
Id: "read",
Name: "Read",
Namespace: &shieldv1.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
{
Id: "write",
Name: "Write",
Namespace: &shieldv1.Namespace{
Id: "resource-1",
Name: "Resource 1",
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
}},
err: nil,
},
}

for _, tt := range table {
t.Run(tt.title, func(t *testing.T) {
t.Parallel()

mockDep := Dep{ActionService: tt.mockActionSrc}
resp, err := mockDep.ListActions(context.Background(), tt.req)

assert.EqualValues(t, tt.want, resp)
assert.EqualValues(t, tt.err, err)
})
}
}

func TestCreateAction(t *testing.T) {
t.Parallel()

table := []struct {
title string
mockActionSrv mockActionSrv
req *shieldv1.CreateActionRequest
want *shieldv1.CreateActionResponse
err error
}{
{
title: "error in creating action",
mockActionSrv: mockActionSrv{CreateActionFunc: func(ctx context.Context, act model.Action) (model.Action, error) {
return model.Action{}, errors.New("some error")
}},
req: &shieldv1.CreateActionRequest{Body: &shieldv1.ActionRequestBody{
Id: "read",
Name: "Read",
NamespaceId: "team",
}},
want: nil,
err: grpcInternalServerError,
},
{
title: "success",
mockActionSrv: mockActionSrv{CreateActionFunc: func(ctx context.Context, act model.Action) (model.Action, error) {
return model.Action{
Id: "read",
Name: "Read",
Namespace: model.Namespace{
Id: "team",
Name: "Team",
},
}, nil
}},
req: &shieldv1.CreateActionRequest{Body: &shieldv1.ActionRequestBody{
Id: "read",
Name: "Read",
NamespaceId: "team",
}},
want: &shieldv1.CreateActionResponse{Action: &shieldv1.Action{
Id: "read",
Name: "Read",
Namespace: &shieldv1.Namespace{
Id: "team",
Name: "Team",
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
},
CreatedAt: timestamppb.New(time.Time{}),
UpdatedAt: timestamppb.New(time.Time{}),
}},
err: nil,
},
}

for _, tt := range table {
t.Run(tt.title, func(t *testing.T) {
t.Parallel()

mockDep := Dep{ActionService: tt.mockActionSrv}
resp, err := mockDep.CreateAction(context.Background(), tt.req)
assert.EqualValues(t, tt.want, resp)
assert.EqualValues(t, tt.err, err)
})
}
}

type mockActionSrv struct {
GetActionFunc func(ctx context.Context, id string) (model.Action, error)
CreateActionFunc func(ctx context.Context, act model.Action) (model.Action, error)
ListActionsFunc func(ctx context.Context) ([]model.Action, error)
UpdateActionFunc func(ctx context.Context, id string, act model.Action) (model.Action, error)
}

func (m mockActionSrv) GetAction(ctx context.Context, id string) (model.Action, error) {
return m.GetActionFunc(ctx, id)
}

func (m mockActionSrv) ListActions(ctx context.Context) ([]model.Action, error) {
return m.ListActionsFunc(ctx)
}

func (m mockActionSrv) CreateAction(ctx context.Context, act model.Action) (model.Action, error) {
return m.CreateActionFunc(ctx, act)
}

func (m mockActionSrv) UpdateAction(ctx context.Context, id string, act model.Action) (model.Action, error) {
return m.UpdateActionFunc(ctx, id, act)
}
Loading