Skip to content

Commit

Permalink
removed generator
Browse files Browse the repository at this point in the history
  • Loading branch information
rrrkren committed Jun 30, 2023
1 parent 540a528 commit ee283eb
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 146 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module github.com/dapperlabs/protoc-gen-go-grpc-scopes
go 1.20

require (
github.com/golang/protobuf v1.5.3
github.com/stretchr/testify v1.8.4
google.golang.org/grpc v1.56.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Expand Down
59 changes: 0 additions & 59 deletions main.go

This file was deleted.

4 changes: 2 additions & 2 deletions proto/scopes.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ message RequiredScopesOption {
repeated string scopes = 1;
}

extend google.protobuf.MessageOptions {
RequiredScopesOption required_req_scopes = 50000; // 50000 is an example, replace it with your desired field number
extend google.protobuf.MethodOptions {
RequiredScopesOption required_method_scopes = 70000;
}
62 changes: 60 additions & 2 deletions scopes/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,78 @@ package scopes

import (
"context"
"fmt"
"strings"

"github.com/dapperlabs/protoc-gen-go-grpc-scopes/scopesproto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/descriptorpb"
)

type ScopeValidator func(ctx context.Context, scopes []string) error

func getMethodDescriptor(info *grpc.UnaryServerInfo) (protoreflect.MethodDescriptor, error) {
// /package.Service/Method
fullMethodSplit := strings.Split(info.FullMethod, "/")

if len(fullMethodSplit) != 3 {
return nil, fmt.Errorf("invalid full method: %s", info.FullMethod)
}

svcFullName := protoreflect.FullName(fullMethodSplit[1])

descriptorByService, err := protoregistry.GlobalFiles.FindDescriptorByName(svcFullName)
if err != nil {
return nil, fmt.Errorf("failed to find service descriptor: %s", err)
}

svc, ok := descriptorByService.(protoreflect.ServiceDescriptor)
if !ok {
return nil, fmt.Errorf("descriptor is not of a service: %s", descriptorByService.FullName())
}

serviceMethod := protoreflect.FullName(info.FullMethod).Name()

// Service/Method
serviceMethodSplit := strings.Split(string(serviceMethod), "/")
if len(serviceMethodSplit) != 2 {
return nil, fmt.Errorf("invalid service method: %s", serviceMethod)
}

methodName := protoreflect.Name(serviceMethodSplit[1])

method := svc.Methods().ByName(methodName)
if method == nil {
return nil, fmt.Errorf("method not found: %s", methodName)
}

return method, nil
}

// ScopeValidationInterceptor validates that the request has the required scopes
func ScopeValidationInterceptor(v ScopeValidator) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
if scopeFetcher, ok := req.(HasScopeRequirements); ok {
if err := v(ctx, scopeFetcher.RequiredScopes()); err != nil {
method, err := getMethodDescriptor(info)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get method descriptor: %s", err)
}

methodOptionsPB := method.Options().(*descriptorpb.MethodOptions)

methodExt := proto.GetExtension(methodOptionsPB, scopesproto.E_RequiredMethodScopes)
if methodExt != nil {
scopesExt := methodExt.(*scopesproto.RequiredScopesOption)

if err := v(ctx, scopesExt.GetScopes()); err != nil {
return nil, err
}
}

return handler(ctx, req)
}
}
13 changes: 12 additions & 1 deletion scopes/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import (
func TestScopeValidationInterceptor(t *testing.T) {
server := grpc.NewServer(
grpc.UnaryInterceptor(scopes.ScopeValidationInterceptor(func(ctx context.Context, scopes []string) error {
if len(scopes) == 0 {
return nil
}
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return status.Error(codes.Unauthenticated, "missing metadata")
Expand Down Expand Up @@ -53,7 +56,7 @@ func TestScopeValidationInterceptor(t *testing.T) {
ctx := metadata.NewOutgoingContext(context.Background(), header)

res, err := client.Ping(ctx, &testgen.PingRequest{})
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, "pong", res.GetPong())

res, err = client.Ping(context.Background(), &testgen.PingRequest{})
Expand All @@ -63,11 +66,19 @@ func TestScopeValidationInterceptor(t *testing.T) {
ctx = metadata.NewOutgoingContext(context.Background(), header)
res, err = client.Ping(ctx, &testgen.PingRequest{})
assert.Equal(t, codes.PermissionDenied, status.Code(err))

res, err = client.FreePing(ctx, &testgen.PingRequest{})
require.NoError(t, err)
assert.Equal(t, "free pong", res.GetPong())
}

type ScopeValidatorServer struct {
}

func (s ScopeValidatorServer) FreePing(ctx context.Context, request *testgen.PingRequest) (*testgen.PingResponse, error) {
return &testgen.PingResponse{Pong: "free pong"}, nil
}

func (s ScopeValidatorServer) Ping(ctx context.Context, request *testgen.PingRequest) (*testgen.PingResponse, error) {
return &testgen.PingResponse{Pong: "pong"}, nil
}
Expand Down
5 changes: 0 additions & 5 deletions scopes/hasscope.go

This file was deleted.

53 changes: 27 additions & 26 deletions scopesproto/scopes.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions test/buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,4 @@ plugins:
out: ./testgen
opt:
- paths=source_relative
- require_unimplemented_servers=false
- name: go-grpc-scopes
out: ./testgen
opt:
- paths=source_relative
- require_unimplemented_servers=false
2 changes: 1 addition & 1 deletion test/buf.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ deps:
- remote: buf.build
owner: rrrkren
repository: protoc-gen-go-grpc-scopes
commit: 1ca8d5541c154b60afd6d65d7f63acee
commit: 65b5b0c776414d3c8f89b8310b77ec1c
7 changes: 0 additions & 7 deletions test/test.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@ package testscopes;

option go_package = "github.com/dapperlabs/protoc-gen-go-grpc-scopes/test/testgen";

import "scopes.proto";
service PingPong {
rpc Ping (PingRequest) returns (PingResponse);
}

message PingRequest {
option (scopes.required_req_scopes).scopes = "scope1";
option (scopes.required_req_scopes).scopes = "scope2";
string ping = 1;
}

Expand Down
Loading

0 comments on commit ee283eb

Please sign in to comment.