Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 20 additions & 3 deletions cmd/buf-plugin-method-options/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,18 @@ var (
LicenseURL: "",
},
}
permissionsOption = commonv1.E_Permissions
restHTTPOption = googleann.E_Http
requiresAuthenticationOption = commonv1.E_RequiresAuthentication

extensionRegistry = map[string]*protoimpl.ExtensionInfo{
"qdrant.cloud.common.v1.permissions": commonv1.E_Permissions,
"google.api.http": googleann.E_Http,
string(permissionsOption.TypeDescriptor().Descriptor().FullName()): permissionsOption,
string(restHTTPOption.TypeDescriptor().Descriptor().FullName()): restHTTPOption,
}
requiredMethodOptionExtensions = []string{
string(permissionsOption.TypeDescriptor().Descriptor().FullName()),
string(restHTTPOption.TypeDescriptor().Descriptor().FullName()),
}
requiredMethodOptionExtensions = []string{"qdrant.cloud.common.v1.permissions", "google.api.http"}
)

func main() {
Expand Down Expand Up @@ -92,6 +99,16 @@ func checkMethodOptions(ctx context.Context, responseWriter check.ResponseWriter
return nil
}
if !proto.HasExtension(options, extension) {
// special case for "qdrant.cloud.common.v1.permissions": in case
// there is "qdrant.cloud.common.v1.requires_authentication" set to
// false, setting permissions isn't needed.
if extensionKey == "qdrant.cloud.common.v1.permissions" && proto.HasExtension(options, requiresAuthenticationOption) {
val := proto.GetExtension(options, requiresAuthenticationOption).(bool)
if !val {
// requires_authentication is false, we skip it.
break
}
}
responseWriter.AddAnnotation(
check.WithMessagef("Method %q does not define the %q option", methodDescriptor.FullName(), extension.TypeDescriptor().FullName()),
check.WithDescriptor(methodDescriptor),
Expand Down
41 changes: 41 additions & 0 deletions cmd/buf-plugin-method-options/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ func TestSimpleFailure(t *testing.T) {
EndColumn: 5,
},
},
{
RuleID: methodOptionsRuleID,
Message: "Method \"simple.GreeterService.ClosedGoodbye\" does not define the \"google.api.http\" option",
FileLocation: &checktest.ExpectedFileLocation{
FileName: "simple.proto",
StartLine: 14,
StartColumn: 4,
EndLine: 18,
EndColumn: 5,
},
},
{
RuleID: methodOptionsRuleID,
Message: "Method \"simple.GreeterService.ClosedGoodbye\" does not define the \"qdrant.cloud.common.v1.permissions\" option",
FileLocation: &checktest.ExpectedFileLocation{
FileName: "simple.proto",
StartLine: 14,
StartColumn: 4,
EndLine: 18,
EndColumn: 5,
},
},
},
}.Run(t)
}
Expand All @@ -81,6 +103,10 @@ func TestSimpleFailureWithOption(t *testing.T) {
RuleID: methodOptionsRuleID,
Message: "extension key \"unknown.extension\" does not exist",
},
{
RuleID: methodOptionsRuleID,
Message: "extension key \"unknown.extension\" does not exist",
},
{
RuleID: methodOptionsRuleID,
Message: "Method \"simple.GreeterService.HelloWorld\" does not define the \"qdrant.cloud.common.v1.permissions\" option",
Expand All @@ -92,6 +118,17 @@ func TestSimpleFailureWithOption(t *testing.T) {
EndColumn: 5,
},
},
{
RuleID: methodOptionsRuleID,
Message: "Method \"simple.GreeterService.ClosedGoodbye\" does not define the \"qdrant.cloud.common.v1.permissions\" option",
FileLocation: &checktest.ExpectedFileLocation{
FileName: "simple.proto",
StartLine: 14,
StartColumn: 4,
EndLine: 18,
EndColumn: 5,
},
},
},
}.Run(t)

Expand All @@ -115,6 +152,10 @@ func TestSimpleFailureWithOptionWrongKey(t *testing.T) {
RuleID: methodOptionsRuleID,
Message: "extension key \"unknown.extension\" does not exist",
},
{
RuleID: methodOptionsRuleID,
Message: "extension key \"unknown.extension\" does not exist",
},
},
}.Run(t)

Expand Down
7 changes: 7 additions & 0 deletions cmd/buf-plugin-method-options/testdata/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@ extend google.protobuf.MethodOptions {
// A list of permissions which ALL need to be met by the current user.
repeated string permissions = 50001;
}

// The extension for allowing a method to be be used without authentication.
// If the extension is missing the system requires authentication and return a 'permission denied' error if missing.
extend google.protobuf.MethodOptions {
// Set to allow a method to be used without authentication.
bool requires_authentication = 50003;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ service GreeterService {
// missing qdrant.cloud.common.v1.permissions
// missing google.api.http
}

rpc ClosedGoodbye(google.protobuf.Empty) returns (google.protobuf.Empty) {
option (qdrant.cloud.common.v1.requires_authentication) = true;
// missing qdrant.cloud.common.v1.permissions
// missing google.api.http
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ service GreeterService {
option (qdrant.cloud.common.v1.permissions) = "read:api_keys";
option (google.api.http) = {get: "/api/hello-world"};
}

rpc OpenGoodbye(google.protobuf.Empty) returns (google.protobuf.Empty) {
// there aren't permissions required because it doesn't require
// authentication.
option (qdrant.cloud.common.v1.requires_authentication) = false;
option (google.api.http) = {get: "/api/hello-world"};
}
}