Add search and status/role/type filters to People
Makes it practical to find people in larger orgs across GraphQL, MCP, CLI, and n8n, with page size raised to 100. Signed-off-by: Sacha Al Himdani <sacha@probo.com>
This commit is contained in:
@@ -12,6 +12,7 @@ type Organization implements Node {
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
filter: ProfileFilter
|
||||
): ProfileConnection @goField(forceResolver: true)
|
||||
|
||||
samlConfigurations(
|
||||
|
||||
@@ -71,6 +71,9 @@ enum ProfileOrderField
|
||||
input ProfileFilter {
|
||||
contractEnded: Boolean
|
||||
state: ProfileState
|
||||
query: String
|
||||
role: MembershipRole
|
||||
kind: String
|
||||
}
|
||||
|
||||
input ProfileOrder
|
||||
|
||||
@@ -31,9 +31,22 @@ func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, fi
|
||||
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||
if filter != nil {
|
||||
filters = coredata.NewMembershipProfileFilter(filter.ContractEnded).WithMembership()
|
||||
|
||||
if filter.State != nil {
|
||||
filters.WithState(*filter.State)
|
||||
}
|
||||
|
||||
if filter.Query != nil {
|
||||
filters.WithQuery(filter.Query)
|
||||
}
|
||||
|
||||
if filter.Role != nil {
|
||||
filters.WithRole(*filter.Role)
|
||||
}
|
||||
|
||||
if filter.Kind != nil {
|
||||
filters.WithKind(filter.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||
|
||||
@@ -179,18 +179,37 @@ func (r *organizationResolver) HorizontalLogo(ctx context.Context, obj *types.Or
|
||||
}
|
||||
|
||||
// Profiles is the resolver for the profiles field.
|
||||
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
|
||||
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
|
||||
if _, err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||
if filter != nil {
|
||||
filters = coredata.NewMembershipProfileFilter(filter.ContractEnded).WithMembership()
|
||||
|
||||
if filter.State != nil {
|
||||
filters.WithState(*filter.State)
|
||||
}
|
||||
|
||||
if filter.Query != nil {
|
||||
filters.WithQuery(filter.Query)
|
||||
}
|
||||
|
||||
if filter.Role != nil {
|
||||
filters.WithRole(*filter.Role)
|
||||
}
|
||||
|
||||
if filter.Kind != nil {
|
||||
filters.WithKind(filter.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||
return &types.ProfileConnection{
|
||||
Resolver: r,
|
||||
ParentID: obj.ID,
|
||||
Filters: filter,
|
||||
Filters: filters,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -207,13 +226,13 @@ func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organiza
|
||||
|
||||
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filter)
|
||||
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filters)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfileConnection(page, r, obj.ID, filter), nil
|
||||
return types.NewProfileConnection(page, r, obj.ID, filters), nil
|
||||
}
|
||||
|
||||
// SamlConfigurations is the resolver for the samlConfigurations field.
|
||||
|
||||
@@ -14,6 +14,17 @@ enum ProfileState
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileStateInactive")
|
||||
}
|
||||
|
||||
enum MembershipRole
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipRole") {
|
||||
OWNER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleOwner")
|
||||
ADMIN @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAdmin")
|
||||
EMPLOYEE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleEmployee")
|
||||
VIEWER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleViewer")
|
||||
AUDITOR
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
|
||||
}
|
||||
|
||||
type Profile implements Node {
|
||||
id: ID!
|
||||
fullName: String!
|
||||
@@ -58,6 +69,9 @@ input ProfileOrder
|
||||
input ProfileFilter {
|
||||
contractEnded: Boolean
|
||||
state: ProfileState
|
||||
query: String
|
||||
role: MembershipRole
|
||||
kind: String
|
||||
}
|
||||
|
||||
type ProfileConnection
|
||||
|
||||
@@ -118,9 +118,22 @@ func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organiza
|
||||
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||
if filter != nil {
|
||||
filters = coredata.NewMembershipProfileFilter(filter.ContractEnded).WithMembership()
|
||||
|
||||
if filter.State != nil {
|
||||
filters.WithState(*filter.State)
|
||||
}
|
||||
|
||||
if filter.Query != nil {
|
||||
filters.WithQuery(filter.Query)
|
||||
}
|
||||
|
||||
if filter.Role != nil {
|
||||
filters.WithRole(*filter.Role)
|
||||
}
|
||||
|
||||
if filter.Kind != nil {
|
||||
filters.WithKind(filter.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
|
||||
|
||||
@@ -2771,9 +2771,23 @@ func (r *Resolver) ListUsersTool(ctx context.Context, req *mcp.CallToolRequest,
|
||||
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
|
||||
if input.Filter != nil {
|
||||
filter = coredata.NewMembershipProfileFilter(input.Filter.ContractEnded).WithMembership()
|
||||
|
||||
if input.Filter.State != nil {
|
||||
filter.WithState(*input.Filter.State)
|
||||
}
|
||||
|
||||
if input.Filter.Query != nil {
|
||||
filter.WithQuery(input.Filter.Query)
|
||||
}
|
||||
|
||||
if input.Filter.Role != nil {
|
||||
filter.WithRole(*input.Filter.Role)
|
||||
}
|
||||
|
||||
if input.Filter.Kind != nil {
|
||||
kind := string(*input.Filter.Kind)
|
||||
filter.WithKind(&kind)
|
||||
}
|
||||
}
|
||||
|
||||
pageResult, err := r.iamSvc.OrganizationService.ListProfiles(ctx, input.OrganizationID, cursor, filter)
|
||||
|
||||
@@ -188,6 +188,13 @@ components:
|
||||
- INACTIVE
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.ProfileState
|
||||
|
||||
ProfileKind:
|
||||
type: string
|
||||
enum:
|
||||
- EMPLOYEE
|
||||
- CONTRACTOR
|
||||
- SERVICE_ACCOUNT
|
||||
|
||||
ProfileSource:
|
||||
type: string
|
||||
enum:
|
||||
@@ -572,6 +579,15 @@ components:
|
||||
state:
|
||||
$ref: "#/components/schemas/ProfileState"
|
||||
description: Filter by profile state (ACTIVE or INACTIVE)
|
||||
query:
|
||||
type: string
|
||||
description: Search by full name, email address, or position
|
||||
role:
|
||||
$ref: "#/components/schemas/MembershipRole"
|
||||
description: Filter by membership role
|
||||
kind:
|
||||
$ref: "#/components/schemas/ProfileKind"
|
||||
description: Filter by profile kind
|
||||
|
||||
ListUsersOutput:
|
||||
type: object
|
||||
|
||||
Reference in New Issue
Block a user