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.87 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 }