diff --git a/docs/docs/apis/proto/system.md b/docs/docs/apis/proto/system.md index 6b0124016c..4005408460 100644 --- a/docs/docs/apis/proto/system.md +++ b/docs/docs/apis/proto/system.md @@ -96,6 +96,19 @@ This might take some time DELETE: /instances/{instance_id} +### ListIAMMembers + +> **rpc** ListIAMMembers([ListIAMMembersRequest](#listiammembersrequest)) +[ListIAMMembersResponse](#listiammembersresponse) + +Returns all instance members matching the request +all queries need to match (ANDed) + + + + POST: /instances/{instance_id}/members/_search + + ### ExistsDomain > **rpc** ExistsDomain([ExistsDomainRequest](#existsdomainrequest)) @@ -614,6 +627,31 @@ This is an empty request +### ListIAMMembersRequest + + + +| Field | Type | Description | Validation | +| ----- | ---- | ----------- | ----------- | +| query | zitadel.v1.ListQuery | - | | +| instance_id | string | - | | +| queries | repeated zitadel.member.v1.SearchQuery | - | | + + + + +### ListIAMMembersResponse + + + +| Field | Type | Description | Validation | +| ----- | ---- | ----------- | ----------- | +| details | zitadel.v1.ListDetails | - | | +| result | repeated zitadel.member.v1.Member | - | | + + + + ### ListInstancesRequest diff --git a/internal/api/grpc/system/instance.go b/internal/api/grpc/system/instance.go index 8d62424b15..822c618bde 100644 --- a/internal/api/grpc/system/instance.go +++ b/internal/api/grpc/system/instance.go @@ -5,6 +5,7 @@ import ( "github.com/zitadel/zitadel/internal/api/authz" instance_grpc "github.com/zitadel/zitadel/internal/api/grpc/instance" + "github.com/zitadel/zitadel/internal/api/grpc/member" "github.com/zitadel/zitadel/internal/api/grpc/object" "github.com/zitadel/zitadel/internal/query" object_pb "github.com/zitadel/zitadel/pkg/grpc/object" @@ -95,6 +96,23 @@ func (s *Server) RemoveInstance(ctx context.Context, req *system_pb.RemoveInstan }, nil } +func (s *Server) ListIAMMembers(ctx context.Context, req *system_pb.ListIAMMembersRequest) (*system_pb.ListIAMMembersResponse, error) { + ctx = authz.WithInstanceID(ctx, req.InstanceId) + queries, err := ListIAMMembersRequestToQuery(req) + if err != nil { + return nil, err + } + res, err := s.query.IAMMembers(ctx, queries, false) + if err != nil { + return nil, err + } + return &system_pb.ListIAMMembersResponse{ + Details: object.ToListDetails(res.Count, res.Sequence, res.Timestamp), + //TODO: resource owner of user of the member instead of the membership resource owner + Result: member.MembersToPb("", res.Members), + }, nil +} + func (s *Server) ExistsDomain(ctx context.Context, req *system_pb.ExistsDomainRequest) (*system_pb.ExistsDomainResponse, error) { domainQuery, err := query.NewInstanceDomainDomainSearchQuery(query.TextEqualsIgnoreCase, req.Domain) if err != nil { diff --git a/internal/api/grpc/system/instance_converter.go b/internal/api/grpc/system/instance_converter.go index 9ef1c343df..2e1a4933bd 100644 --- a/internal/api/grpc/system/instance_converter.go +++ b/internal/api/grpc/system/instance_converter.go @@ -8,6 +8,7 @@ import ( "github.com/zitadel/zitadel/internal/api/grpc/authn" instance_grpc "github.com/zitadel/zitadel/internal/api/grpc/instance" + member_grpc "github.com/zitadel/zitadel/internal/api/grpc/member" "github.com/zitadel/zitadel/internal/api/grpc/object" z_oidc "github.com/zitadel/zitadel/internal/api/oidc" "github.com/zitadel/zitadel/internal/command" @@ -260,3 +261,22 @@ func fieldNameToInstanceDomainColumn(fieldName instance_pb.DomainFieldName) quer return query.Column{} } } + +func ListIAMMembersRequestToQuery(req *system_pb.ListIAMMembersRequest) (*query.IAMMembersQuery, error) { + offset, limit, asc := object.ListQueryToModel(req.Query) + queries, err := member_grpc.MemberQueriesToQuery(req.Queries) + if err != nil { + return nil, err + } + return &query.IAMMembersQuery{ + MembersQuery: query.MembersQuery{ + SearchRequest: query.SearchRequest{ + Offset: offset, + Limit: limit, + Asc: asc, + // SortingColumn: model.IAMMemberSearchKey, //TOOD: not implemented in proto + }, + Queries: queries, + }, + }, nil +} diff --git a/proto/zitadel/system.proto b/proto/zitadel/system.proto index 7b1f7d52c3..9b8c3edc6e 100644 --- a/proto/zitadel/system.proto +++ b/proto/zitadel/system.proto @@ -3,6 +3,7 @@ syntax = "proto3"; import "zitadel/object.proto"; import "zitadel/options.proto"; import "zitadel/instance.proto"; +import "zitadel/member.proto"; import "zitadel/auth_n_key.proto"; import "google/api/annotations.proto"; @@ -173,6 +174,19 @@ service SystemService { }; } + //Returns all instance members matching the request + // all queries need to match (ANDed) + rpc ListIAMMembers(ListIAMMembersRequest) returns (ListIAMMembersResponse) { + option (google.api.http) = { + post: "/instances/{instance_id}/members/_search"; + body: "*"; + }; + + option (zitadel.v1.auth_option) = { + permission: "authenticated"; + }; + } + // Checks if a domain exists rpc ExistsDomain(ExistsDomainRequest) returns (ExistsDomainResponse) { option (google.api.http) = { @@ -491,6 +505,17 @@ message RemoveInstanceResponse { zitadel.v1.ObjectDetails details = 1; } +message ListIAMMembersRequest { + zitadel.v1.ListQuery query = 1; + string instance_id = 2; + repeated zitadel.member.v1.SearchQuery queries = 3; +} + +message ListIAMMembersResponse { + zitadel.v1.ListDetails details = 1; + repeated zitadel.member.v1.Member result = 2; +} + message GetUsageRequest { string instance_id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}]; }