Files
probo/pkg/server/api/connect/v1/base_resolvers.go
Sacha Al Himdani 88242eed87 Restore MCP cross-origin protection after go-sdk v1.6.0 bump
The go-sdk v1.6.0 release no longer applies a default
CrossOriginProtection when the field is nil in StreamableHTTPOptions,
silently removing Origin header verification. Wrap the streamable
handler with http.NewCrossOriginProtection().Handler(...) (the
recommended replacement, since the SDK field is deprecated).

Also regenerate gqlgen resolvers to track v0.17.90.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-05 14:46:04 +02:00

259 lines
7.9 KiB
Go

package connect_v1
// This file will be automatically regenerated based on the schema, any resolver
// implementations
// will be copied through when generating and any unknown code will be moved to the end.
// Code generated by github.com/99designs/gqlgen version v0.17.90
import (
"context"
"errors"
"fmt"
"strings"
"github.com/99designs/gqlgen/graphql"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/iam/oauth2server"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
)
// Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
var (
loadNode func(ctx context.Context, id gid.GID) (types.Node, error)
action string
)
switch id.EntityType() {
case coredata.OAuth2ConsentEntityType:
action = iam.ActionOAuth2ConsentGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
consent, err := r.iam.OAuth2ServerService.GetConsentByID(ctx, id)
if err != nil {
return nil, err
}
return types.NewConsent(consent), nil
}
case coredata.OrganizationEntityType:
action = iam.ActionOrganizationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
organization, err := r.iam.OrganizationService.GetOrganization(ctx, id)
if err != nil {
return nil, err
}
return types.NewOrganization(organization), nil
}
case coredata.IdentityEntityType:
action = iam.ActionIdentityGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
identity, err := r.iam.AccountService.GetIdentity(ctx, id)
if err != nil {
return nil, err
}
return types.NewIdentity(identity), nil
}
case coredata.SessionEntityType:
action = iam.ActionSessionGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
session, err := r.iam.GetSession(ctx, id)
if err != nil {
return nil, err
}
return types.NewSession(session), nil
}
case coredata.MembershipProfileEntityType:
action = iam.ActionMembershipGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
profile, err := r.iam.OrganizationService.GetProfile(ctx, id)
if err != nil {
return nil, err
}
return types.NewProfile(profile), nil
}
case coredata.MembershipEntityType:
action = iam.ActionMembershipGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
membership, err := r.iam.GetMembership(ctx, id)
if err != nil {
return nil, err
}
return types.NewMembership(membership), nil
}
case coredata.InvitationEntityType:
action = iam.ActionInvitationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
invitation, err := r.iam.GetInvitation(ctx, id)
if err != nil {
return nil, err
}
return types.NewInvitation(invitation), nil
}
case coredata.SAMLConfigurationEntityType:
action = iam.ActionSAMLConfigurationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
samlConfiguration, err := r.iam.GetSAMLconfiguration(ctx, id)
if err != nil {
return nil, err
}
return types.NewSAMLConfiguration(samlConfiguration), nil
}
case coredata.PersonalAPIKeyEntityType:
action = iam.ActionPersonalAPIKeyGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
personalAPIKey, err := r.iam.GetPersonalAPIKey(ctx, id)
if err != nil {
return nil, err
}
return types.NewPersonalAPIKey(personalAPIKey), nil
}
case coredata.SCIMConfigurationEntityType:
action = iam.ActionSCIMConfigurationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
scimConfiguration, err := r.iam.GetSCIMConfiguration(ctx, id)
if err != nil {
return nil, err
}
return types.NewSCIMConfiguration(scimConfiguration), nil
}
case coredata.SCIMEventEntityType:
action = iam.ActionSCIMEventGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
scimEvent, err := r.iam.GetSCIMEvent(ctx, id)
if err != nil {
return nil, err
}
return types.NewSCIMEvent(scimEvent), nil
}
default:
return nil, fmt.Errorf("unsupported entity type: %d", id.EntityType())
}
if err := r.authorize(ctx, id, action); err != nil {
return nil, err
}
node, err := loadNode(ctx, id)
if err != nil {
var (
errOrganizationNotFound *iam.ErrOrganizationNotFound
errIdentityNotFound *iam.ErrIdentityNotFound
errSessionNotFound *iam.ErrSessionNotFound
errProfileNotFound *iam.ErrProfileNotFound
errMembershipNotFound *iam.ErrMembershipNotFound
errInvitationNotFound *iam.ErrInvitationNotFound
isNotFoundErr = errors.As(err, &errOrganizationNotFound) ||
errors.As(err, &errIdentityNotFound) ||
errors.As(err, &errSessionNotFound) ||
errors.As(err, &errProfileNotFound) ||
errors.As(err, &errMembershipNotFound) ||
errors.As(err, &errInvitationNotFound)
)
if isNotFoundErr {
return nil, gqlutils.NotFound(ctx, err)
}
if oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err); ok {
return nil, gqlutils.Invalidf(ctx, "%s", oauthErr.Description())
}
r.logger.ErrorCtx(ctx, "cannot load node", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return node, nil
}
// Viewer is the resolver for the viewer field.
func (r *queryResolver) Viewer(ctx context.Context) (*types.Identity, error) {
identity := authn.IdentityFromContext(ctx)
return &types.Identity{
ID: identity.ID,
Email: identity.EmailAddress,
EmailVerified: identity.EmailAddressVerified,
FullName: identity.FullName,
CreatedAt: identity.CreatedAt,
UpdatedAt: identity.UpdatedAt,
}, nil
}
// SsoLoginURL is the resolver for the ssoLoginURL field.
func (r *queryResolver) SsoLoginURL(ctx context.Context, email mail.Addr) (*string, error) {
count, err := r.iam.AccountService.CountSAMLConfigurationsForEmail(ctx, email)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot count SAML configurations for email", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if count != 1 {
if count == 0 {
return nil, graphql.ErrorOnPath(
ctx,
fmt.Errorf("no SAML configuration for email"),
)
}
return nil, graphql.ErrorOnPath(
ctx,
fmt.Errorf("multiple SSO configurations found for this domain. Please use your organization-specific SSO login URL"),
)
}
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, email)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list SAML configurations for email", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
samlConfig := samlConfigs[0]
loginURL := r.SSOLoginURL(samlConfig.ID)
return &loginURL, nil
}
// OidcProviders is the resolver for the oidcProviders field.
func (r *queryResolver) OidcProviders(ctx context.Context) ([]*types.OIDCProviderInfo, error) {
providers := r.iam.OIDCService.EnabledProviders()
result := make([]*types.OIDCProviderInfo, 0, len(providers))
for _, p := range providers {
result = append(result, &types.OIDCProviderInfo{
Name: strings.ToLower(p.String()),
LoginURL: r.baseURL.WithPath("/api/connect/v1/oidc/" + strings.ToLower(p.String()) + "/login").MustString(),
})
}
return result, nil
}
// SignUpEnabled is the resolver for the signUpEnabled field.
func (r *queryResolver) SignUpEnabled(ctx context.Context) (bool, error) {
return r.iam.IsSignUpEnabled(), nil
}
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }