Skip to content
Merged
23 changes: 8 additions & 15 deletions api/handler/v1/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
grpczap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"

"github.com/odpf/shield/internal/org"
modelv1 "github.com/odpf/shield/model/v1"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand All @@ -18,20 +19,12 @@ import (
)

type OrganizationService interface {
GetOrganization(ctx context.Context, id string) (org.Organization, error)
CreateOrganization(ctx context.Context, org org.Organization) (org.Organization, error)
ListOrganizations(ctx context.Context) ([]org.Organization, error)
UpdateOrganization(ctx context.Context, toUpdate org.Organization) (org.Organization, error)
GetOrganization(ctx context.Context, id string) (modelv1.Organization, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krtkvrm I think we don't need to version internal models. So would suggest removing versioning from here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah.. makes sense 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

CreateOrganization(ctx context.Context, org modelv1.Organization) (modelv1.Organization, error)
ListOrganizations(ctx context.Context) ([]modelv1.Organization, error)
UpdateOrganization(ctx context.Context, toUpdate modelv1.Organization) (modelv1.Organization, error)
}

var (
grpcInternalServerError = status.Errorf(codes.Internal, internalServerError.Error())
grpcBadBodyError = status.Error(codes.InvalidArgument, badRequestError.Error())
)

// HTTP Codes defined here:
// https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/errors.go#L36

func (v Dep) ListOrganizations(ctx context.Context, request *shieldv1.ListOrganizationsRequest) (*shieldv1.ListOrganizationsResponse, error) {
logger := grpczap.Extract(ctx)
var orgs []*shieldv1.Organization
Expand Down Expand Up @@ -76,7 +69,7 @@ func (v Dep) CreateOrganization(ctx context.Context, request *shieldv1.CreateOrg
slug = generateSlug(request.GetBody().Name)
}

newOrg, err := v.OrgService.CreateOrganization(ctx, org.Organization{
newOrg, err := v.OrgService.CreateOrganization(ctx, modelv1.Organization{
Name: request.GetBody().Name,
Slug: slug,
Metadata: metaDataMap,
Expand Down Expand Up @@ -142,7 +135,7 @@ func (v Dep) UpdateOrganization(ctx context.Context, request *shieldv1.UpdateOrg
return nil, grpcBadBodyError
}

updatedOrg, err := v.OrgService.UpdateOrganization(ctx, org.Organization{
updatedOrg, err := v.OrgService.UpdateOrganization(ctx, modelv1.Organization{
Id: request.GetId(),
Name: request.GetBody().Name,
Slug: request.GetBody().Slug,
Expand All @@ -163,7 +156,7 @@ func (v Dep) UpdateOrganization(ctx context.Context, request *shieldv1.UpdateOrg
return &shieldv1.UpdateOrganizationResponse{Organization: &orgPB}, nil
}

func transformOrgToPB(org org.Organization) (shieldv1.Organization, error) {
func transformOrgToPB(org modelv1.Organization) (shieldv1.Organization, error) {
metaData, err := structpb.NewStruct(mapOfInterfaceValues(org.Metadata))
if err != nil {
return shieldv1.Organization{}, err
Expand Down
38 changes: 19 additions & 19 deletions api/handler/v1/org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"testing"
"time"

"github.com/odpf/shield/internal/org"

"github.com/stretchr/testify/assert"

modelv1 "github.com/odpf/shield/model/v1"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
Expand All @@ -18,7 +18,7 @@ import (
shieldv1 "go.buf.build/odpf/gw/odpf/proton/odpf/shield/v1"
)

var testOrgMap = map[string]org.Organization{
var testOrgMap = map[string]modelv1.Organization{
"9f256f86-31a3-11ec-8d3d-0242ac130003": {
Id: "9f256f86-31a3-11ec-8d3d-0242ac130003",
Name: "Org 1",
Expand All @@ -42,15 +42,15 @@ func TestListOrganizations(t *testing.T) {
}{
{
title: "error in Org Service",
mockOrgSrv: mockOrgSrv{ListOrganizationsFunc: func(ctx context.Context) (organizations []org.Organization, err error) {
return []org.Organization{}, errors.New("some error")
mockOrgSrv: mockOrgSrv{ListOrganizationsFunc: func(ctx context.Context) (organizations []modelv1.Organization, err error) {
return []modelv1.Organization{}, errors.New("some error")
}},
want: nil,
err: status.Errorf(codes.Internal, internalServerError.Error()),
}, {
title: "success",
mockOrgSrv: mockOrgSrv{ListOrganizationsFunc: func(ctx context.Context) (organizations []org.Organization, err error) {
var testOrgList []org.Organization
mockOrgSrv: mockOrgSrv{ListOrganizationsFunc: func(ctx context.Context) (organizations []modelv1.Organization, err error) {
var testOrgList []modelv1.Organization
for _, o := range testOrgMap {
testOrgList = append(testOrgList, o)
}
Expand Down Expand Up @@ -98,8 +98,8 @@ func TestCreateOrganization(t *testing.T) {
}{
{
title: "error in fetching org list",
mockOrgSrv: mockOrgSrv{CreateOrganizationFunc: func(ctx context.Context, o org.Organization) (org.Organization, error) {
return org.Organization{}, errors.New("some error")
mockOrgSrv: mockOrgSrv{CreateOrganizationFunc: func(ctx context.Context, o modelv1.Organization) (modelv1.Organization, error) {
return modelv1.Organization{}, errors.New("some error")
}},
req: &shieldv1.CreateOrganizationRequest{Body: &shieldv1.OrganizationRequestBody{
Name: "some org",
Expand All @@ -125,8 +125,8 @@ func TestCreateOrganization(t *testing.T) {
},
{
title: "success",
mockOrgSrv: mockOrgSrv{CreateOrganizationFunc: func(ctx context.Context, o org.Organization) (org.Organization, error) {
return org.Organization{
mockOrgSrv: mockOrgSrv{CreateOrganizationFunc: func(ctx context.Context, o modelv1.Organization) (modelv1.Organization, error) {
return modelv1.Organization{
Id: "new-abc",
Name: "some org",
Slug: "abc",
Expand Down Expand Up @@ -167,24 +167,24 @@ func TestCreateOrganization(t *testing.T) {
}

type mockOrgSrv struct {
GetOrganizationFunc func(ctx context.Context, id string) (org.Organization, error)
CreateOrganizationFunc func(ctx context.Context, org org.Organization) (org.Organization, error)
ListOrganizationsFunc func(ctx context.Context) ([]org.Organization, error)
UpdateOrganizationFunc func(ctx context.Context, toUpdate org.Organization) (org.Organization, error)
GetOrganizationFunc func(ctx context.Context, id string) (modelv1.Organization, error)
CreateOrganizationFunc func(ctx context.Context, org modelv1.Organization) (modelv1.Organization, error)
ListOrganizationsFunc func(ctx context.Context) ([]modelv1.Organization, error)
UpdateOrganizationFunc func(ctx context.Context, toUpdate modelv1.Organization) (modelv1.Organization, error)
}

func (m mockOrgSrv) GetOrganization(ctx context.Context, id string) (org.Organization, error) {
func (m mockOrgSrv) GetOrganization(ctx context.Context, id string) (modelv1.Organization, error) {
return m.GetOrganizationFunc(ctx, id)
}

func (m mockOrgSrv) CreateOrganization(ctx context.Context, org org.Organization) (org.Organization, error) {
func (m mockOrgSrv) CreateOrganization(ctx context.Context, org modelv1.Organization) (modelv1.Organization, error) {
return m.CreateOrganizationFunc(ctx, org)
}

func (m mockOrgSrv) ListOrganizations(ctx context.Context) ([]org.Organization, error) {
func (m mockOrgSrv) ListOrganizations(ctx context.Context) ([]modelv1.Organization, error) {
return m.ListOrganizationsFunc(ctx)
}

func (m mockOrgSrv) UpdateOrganization(ctx context.Context, toUpdate org.Organization) (org.Organization, error) {
func (m mockOrgSrv) UpdateOrganization(ctx context.Context, toUpdate modelv1.Organization) (modelv1.Organization, error) {
return m.UpdateOrganizationFunc(ctx, toUpdate)
}
143 changes: 139 additions & 4 deletions api/handler/v1/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,160 @@ package v1

import (
"context"
"errors"
"strings"

grpczap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"

"github.com/odpf/shield/internal/project"
modelv1 "github.com/odpf/shield/model/v1"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"

shieldv1 "go.buf.build/odpf/gw/odpf/proton/odpf/shield/v1"
)

var grpcProjectNotFoundErr = status.Errorf(codes.NotFound, "project doesn't exist")

type ProjectService interface {
Get(ctx context.Context, id string) (modelv1.Project, error)
Create(ctx context.Context, project modelv1.Project) (modelv1.Project, error)
List(ctx context.Context) ([]modelv1.Project, error)
Update(ctx context.Context, toUpdate modelv1.Project) (modelv1.Project, error)
}

func (v Dep) ListProjects(ctx context.Context, request *shieldv1.ListProjectsRequest) (*shieldv1.ListProjectsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method not implemented")
logger := grpczap.Extract(ctx)
var projects []*shieldv1.Project

projectList, err := v.ProjectService.List(ctx)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

for _, v := range projectList {
projectPB, err := transformProjectToPB(v)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

projects = append(projects, &projectPB)
}

return &shieldv1.ListProjectsResponse{Projects: projects}, nil
}

func (v Dep) CreateProject(ctx context.Context, request *shieldv1.CreateProjectRequest) (*shieldv1.CreateProjectResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method not implemented")
logger := grpczap.Extract(ctx)
metaDataMap, err := mapOfStringValues(request.GetBody().Metadata.AsMap())
if err != nil {
logger.Error(err.Error())
return nil, grpcBadBodyError
}

slug := request.GetBody().Slug
if strings.TrimSpace(slug) == "" {
slug = generateSlug(request.GetBody().Name)
}

newProject, err := v.ProjectService.Create(ctx, modelv1.Project{
Name: request.GetBody().Name,
Slug: slug,
Metadata: metaDataMap,
//Organization: org.Organization{Id: "ACCEPT"},
})

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

metaData, err := structpb.NewStruct(mapOfInterfaceValues(newProject.Metadata))
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.CreateProjectResponse{Project: &shieldv1.Project{
Id: newProject.Id,
Name: newProject.Name,
Slug: newProject.Slug,
Metadata: metaData,
CreatedAt: timestamppb.New(newProject.CreatedAt),
UpdatedAt: timestamppb.New(newProject.UpdatedAt),
}}, nil
}

func (v Dep) GetProject(ctx context.Context, request *shieldv1.GetProjectRequest) (*shieldv1.GetProjectResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method not implemented")
logger := grpczap.Extract(ctx)

fetchedProject, err := v.ProjectService.Get(ctx, request.GetId())
if err != nil {
logger.Error(err.Error())
switch {
case errors.Is(err, project.ProjectDoesntExist):
return nil, grpcProjectNotFoundErr
case errors.Is(err, project.InvalidUUID):
return nil, grpcBadBodyError
default:
return nil, grpcInternalServerError
}
}

projectPB, err := transformProjectToPB(fetchedProject)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.GetProjectResponse{Project: &projectPB}, nil
}

func (v Dep) UpdateProject(ctx context.Context, request *shieldv1.UpdateProjectRequest) (*shieldv1.UpdateProjectResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method not implemented")
logger := grpczap.Extract(ctx)

metaDataMap, err := mapOfStringValues(request.GetBody().Metadata.AsMap())
if err != nil {
return nil, grpcBadBodyError
}

updatedProject, err := v.ProjectService.Update(ctx, modelv1.Project{
Id: request.GetId(),
Name: request.GetBody().Name,
Slug: request.GetBody().Slug,
Metadata: metaDataMap,
})
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

projectPB, err := transformProjectToPB(updatedProject)
if err != nil {
logger.Error(err.Error())
return nil, grpcInternalServerError
}

return &shieldv1.UpdateProjectResponse{Project: &projectPB}, nil
}

func transformProjectToPB(prj modelv1.Project) (shieldv1.Project, error) {
metaData, err := structpb.NewStruct(mapOfInterfaceValues(prj.Metadata))
if err != nil {
return shieldv1.Project{}, err
}

return shieldv1.Project{
Id: prj.Id,
Name: prj.Name,
Slug: prj.Slug,
Metadata: metaData,
CreatedAt: timestamppb.New(prj.CreatedAt),
UpdatedAt: timestamppb.New(prj.UpdatedAt),
}, nil
}
Loading