Files
probo/pkg/server/api/connect/v1/base_resolvers.go
Émile Ré f5703d390b Enforce Go style rules across codebase
Apply five style rules: convert iota string enums to typed
string constants, replace errors.As with errors.AsType,
merge three-group imports into two groups, fix multiline
parameter/argument formatting, and replace fmt.Sprintf URL
construction with net/url.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 11:46:39 +04:00

267 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 {
if _, ok := errors.AsType[*iam.ErrOrganizationNotFound](err); ok {
return nil, gqlutils.NotFound(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrIdentityNotFound](err); ok {
return nil, gqlutils.NotFound(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrSessionNotFound](err); ok {
return nil, gqlutils.NotFound(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok {
return nil, gqlutils.NotFound(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrMembershipNotFound](err); ok {
return nil, gqlutils.NotFound(ctx, err)
}
if _, ok := errors.AsType[*iam.ErrInvitationNotFound](err); ok {
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 }