mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:27:42 +00:00
feat: exchange gRPC server implementation to connectRPC (#10145)
# Which Problems Are Solved The current maintained gRPC server in combination with a REST (grpc) gateway is getting harder and harder to maintain. Additionally, there have been and still are issues with supporting / displaying `oneOf`s correctly. We therefore decided to exchange the server implementation to connectRPC, which apart from supporting connect as protocol, also also "standard" gRCP clients as well as HTTP/1.1 / rest like clients, e.g. curl directly call the server without any additional gateway. # How the Problems Are Solved - All v2 services are moved to connectRPC implementation. (v1 services are still served as pure grpc servers) - All gRPC server interceptors were migrated / copied to a corresponding connectRPC interceptor. - API.ListGrpcServices and API. ListGrpcMethods were changed to include the connect services and endpoints. - gRPC server reflection was changed to a `StaticReflector` using the `ListGrpcServices` list. - The `grpc.Server` interfaces was split into different combinations to be able to handle the different cases (grpc server and prefixed gateway, connect server with grpc gateway, connect server only, ...) - Docs of services serving connectRPC only with no additional gateway (instance, webkey, project, app, org v2 beta) are changed to expose that - since the plugin is not yet available on buf, we download it using `postinstall` hook of the docs # Additional Changes - WebKey service is added as v2 service (in addition to the current v2beta) # Additional Context closes #9483 --------- Co-authored-by: Elio Bischof <elio@zitadel.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package action
|
||||
import (
|
||||
"context"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
@@ -13,8 +14,8 @@ import (
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v2beta"
|
||||
)
|
||||
|
||||
func (s *Server) SetExecution(ctx context.Context, req *action.SetExecutionRequest) (*action.SetExecutionResponse, error) {
|
||||
reqTargets := req.GetTargets()
|
||||
func (s *Server) SetExecution(ctx context.Context, req *connect.Request[action.SetExecutionRequest]) (*connect.Response[action.SetExecutionResponse], error) {
|
||||
reqTargets := req.Msg.GetTargets()
|
||||
targets := make([]*execution.Target, len(reqTargets))
|
||||
for i, target := range reqTargets {
|
||||
targets[i] = &execution.Target{Type: domain.ExecutionTargetTypeTarget, Target: target}
|
||||
@@ -25,7 +26,7 @@ func (s *Server) SetExecution(ctx context.Context, req *action.SetExecutionReque
|
||||
var err error
|
||||
var details *domain.ObjectDetails
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
switch t := req.GetCondition().GetConditionType().(type) {
|
||||
switch t := req.Msg.GetCondition().GetConditionType().(type) {
|
||||
case *action.Condition_Request:
|
||||
cond := executionConditionFromRequest(t.Request)
|
||||
details, err = s.command.SetExecutionRequest(ctx, cond, set, instanceID)
|
||||
@@ -43,27 +44,27 @@ func (s *Server) SetExecution(ctx context.Context, req *action.SetExecutionReque
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &action.SetExecutionResponse{
|
||||
return connect.NewResponse(&action.SetExecutionResponse{
|
||||
SetDate: timestamppb.New(details.EventDate),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) ListExecutionFunctions(ctx context.Context, _ *action.ListExecutionFunctionsRequest) (*action.ListExecutionFunctionsResponse, error) {
|
||||
return &action.ListExecutionFunctionsResponse{
|
||||
func (s *Server) ListExecutionFunctions(ctx context.Context, _ *connect.Request[action.ListExecutionFunctionsRequest]) (*connect.Response[action.ListExecutionFunctionsResponse], error) {
|
||||
return connect.NewResponse(&action.ListExecutionFunctionsResponse{
|
||||
Functions: s.ListActionFunctions(),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) ListExecutionMethods(ctx context.Context, _ *action.ListExecutionMethodsRequest) (*action.ListExecutionMethodsResponse, error) {
|
||||
return &action.ListExecutionMethodsResponse{
|
||||
func (s *Server) ListExecutionMethods(ctx context.Context, _ *connect.Request[action.ListExecutionMethodsRequest]) (*connect.Response[action.ListExecutionMethodsResponse], error) {
|
||||
return connect.NewResponse(&action.ListExecutionMethodsResponse{
|
||||
Methods: s.ListGRPCMethods(),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) ListExecutionServices(ctx context.Context, _ *action.ListExecutionServicesRequest) (*action.ListExecutionServicesResponse, error) {
|
||||
return &action.ListExecutionServicesResponse{
|
||||
func (s *Server) ListExecutionServices(ctx context.Context, _ *connect.Request[action.ListExecutionServicesRequest]) (*connect.Response[action.ListExecutionServicesResponse], error) {
|
||||
return connect.NewResponse(&action.ListExecutionServicesResponse{
|
||||
Services: s.ListGRPCServices(),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func executionConditionFromRequest(request *action.RequestExecution) *command.ExecutionAPICondition {
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
@@ -22,14 +23,14 @@ const (
|
||||
conditionIDEventGroupSegmentCount = 1
|
||||
)
|
||||
|
||||
func (s *Server) GetTarget(ctx context.Context, req *action.GetTargetRequest) (*action.GetTargetResponse, error) {
|
||||
resp, err := s.query.GetTargetByID(ctx, req.GetId())
|
||||
func (s *Server) GetTarget(ctx context.Context, req *connect.Request[action.GetTargetRequest]) (*connect.Response[action.GetTargetResponse], error) {
|
||||
resp, err := s.query.GetTargetByID(ctx, req.Msg.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &action.GetTargetResponse{
|
||||
return connect.NewResponse(&action.GetTargetResponse{
|
||||
Target: targetToPb(resp),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
type InstanceContext interface {
|
||||
@@ -41,8 +42,8 @@ type Context interface {
|
||||
GetOwner() InstanceContext
|
||||
}
|
||||
|
||||
func (s *Server) ListTargets(ctx context.Context, req *action.ListTargetsRequest) (*action.ListTargetsResponse, error) {
|
||||
queries, err := s.ListTargetsRequestToModel(req)
|
||||
func (s *Server) ListTargets(ctx context.Context, req *connect.Request[action.ListTargetsRequest]) (*connect.Response[action.ListTargetsResponse], error) {
|
||||
queries, err := s.ListTargetsRequestToModel(req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,14 +51,14 @@ func (s *Server) ListTargets(ctx context.Context, req *action.ListTargetsRequest
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &action.ListTargetsResponse{
|
||||
return connect.NewResponse(&action.ListTargetsResponse{
|
||||
Result: targetsToPb(resp.Targets),
|
||||
Pagination: filter.QueryToPaginationPb(queries.SearchRequest, resp.SearchResponse),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) ListExecutions(ctx context.Context, req *action.ListExecutionsRequest) (*action.ListExecutionsResponse, error) {
|
||||
queries, err := s.ListExecutionsRequestToModel(req)
|
||||
func (s *Server) ListExecutions(ctx context.Context, req *connect.Request[action.ListExecutionsRequest]) (*connect.Response[action.ListExecutionsResponse], error) {
|
||||
queries, err := s.ListExecutionsRequestToModel(req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -65,10 +66,10 @@ func (s *Server) ListExecutions(ctx context.Context, req *action.ListExecutionsR
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &action.ListExecutionsResponse{
|
||||
return connect.NewResponse(&action.ListExecutionsResponse{
|
||||
Result: executionsToPb(resp.Executions),
|
||||
Pagination: filter.QueryToPaginationPb(queries.SearchRequest, resp.SearchResponse),
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func targetsToPb(targets []*query.Target) []*action.Target {
|
||||
|
@@ -1,7 +1,10 @@
|
||||
package action
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc"
|
||||
"net/http"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/server"
|
||||
@@ -9,12 +12,12 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/action/v2beta/actionconnect"
|
||||
)
|
||||
|
||||
var _ action.ActionServiceServer = (*Server)(nil)
|
||||
var _ actionconnect.ActionServiceHandler = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
action.UnimplementedActionServiceServer
|
||||
systemDefaults systemdefaults.SystemDefaults
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
@@ -43,8 +46,12 @@ func CreateServer(
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) RegisterServer(grpcServer *grpc.Server) {
|
||||
action.RegisterActionServiceServer(grpcServer, s)
|
||||
func (s *Server) RegisterConnectServer(interceptors ...connect.Interceptor) (string, http.Handler) {
|
||||
return actionconnect.NewActionServiceHandler(s, connect.WithInterceptors(interceptors...))
|
||||
}
|
||||
|
||||
func (s *Server) FileDescriptor() protoreflect.FileDescriptor {
|
||||
return action.File_zitadel_action_v2beta_action_service_proto
|
||||
}
|
||||
|
||||
func (s *Server) AppName() string {
|
||||
|
@@ -3,6 +3,7 @@ package action
|
||||
import (
|
||||
"context"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/muhlemmer/gu"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
@@ -13,8 +14,8 @@ import (
|
||||
action "github.com/zitadel/zitadel/pkg/grpc/action/v2beta"
|
||||
)
|
||||
|
||||
func (s *Server) CreateTarget(ctx context.Context, req *action.CreateTargetRequest) (*action.CreateTargetResponse, error) {
|
||||
add := createTargetToCommand(req)
|
||||
func (s *Server) CreateTarget(ctx context.Context, req *connect.Request[action.CreateTargetRequest]) (*connect.Response[action.CreateTargetResponse], error) {
|
||||
add := createTargetToCommand(req.Msg)
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
createdAt, err := s.command.AddTarget(ctx, add, instanceID)
|
||||
if err != nil {
|
||||
@@ -24,16 +25,16 @@ func (s *Server) CreateTarget(ctx context.Context, req *action.CreateTargetReque
|
||||
if !createdAt.IsZero() {
|
||||
creationDate = timestamppb.New(createdAt)
|
||||
}
|
||||
return &action.CreateTargetResponse{
|
||||
return connect.NewResponse(&action.CreateTargetResponse{
|
||||
Id: add.AggregateID,
|
||||
CreationDate: creationDate,
|
||||
SigningKey: add.SigningKey,
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateTarget(ctx context.Context, req *action.UpdateTargetRequest) (*action.UpdateTargetResponse, error) {
|
||||
func (s *Server) UpdateTarget(ctx context.Context, req *connect.Request[action.UpdateTargetRequest]) (*connect.Response[action.UpdateTargetResponse], error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
update := updateTargetToCommand(req)
|
||||
update := updateTargetToCommand(req.Msg)
|
||||
changedAt, err := s.command.ChangeTarget(ctx, update, instanceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -42,15 +43,15 @@ func (s *Server) UpdateTarget(ctx context.Context, req *action.UpdateTargetReque
|
||||
if !changedAt.IsZero() {
|
||||
changeDate = timestamppb.New(changedAt)
|
||||
}
|
||||
return &action.UpdateTargetResponse{
|
||||
return connect.NewResponse(&action.UpdateTargetResponse{
|
||||
ChangeDate: changeDate,
|
||||
SigningKey: update.SigningKey,
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) DeleteTarget(ctx context.Context, req *action.DeleteTargetRequest) (*action.DeleteTargetResponse, error) {
|
||||
func (s *Server) DeleteTarget(ctx context.Context, req *connect.Request[action.DeleteTargetRequest]) (*connect.Response[action.DeleteTargetResponse], error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
deletedAt, err := s.command.DeleteTarget(ctx, req.GetId(), instanceID)
|
||||
deletedAt, err := s.command.DeleteTarget(ctx, req.Msg.GetId(), instanceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,9 +59,9 @@ func (s *Server) DeleteTarget(ctx context.Context, req *action.DeleteTargetReque
|
||||
if !deletedAt.IsZero() {
|
||||
deletionDate = timestamppb.New(deletedAt)
|
||||
}
|
||||
return &action.DeleteTargetResponse{
|
||||
return connect.NewResponse(&action.DeleteTargetResponse{
|
||||
DeletionDate: deletionDate,
|
||||
}, nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
func createTargetToCommand(req *action.CreateTargetRequest) *command.AddTarget {
|
||||
|
Reference in New Issue
Block a user