Replug SAML configurations

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-24 11:15:31 +01:00
committed by Bryan Frimin
parent 600d763d18
commit b012b5ec42
24 changed files with 2230 additions and 121 deletions

View File

@@ -300,8 +300,7 @@ type SAMLConfiguration implements Node {
autoSignupEnabled: Boolean!
createdAt: Datetime!
updatedAt: Datetime!
spMetadataUrl: String!
testLoginUrl: String!
testLoginUrl: String! @goField(forceResolver: true)
attributeMappings: SAMLAttributeMappings!
}
@@ -640,7 +639,7 @@ input UpdateSAMLConfigurationInput {
idpSsoUrl: String
idpCertificate: String
autoSignupEnabled: Boolean
enforcementPolicy: SAMLEnforcementPolicy
enforcementPolicy: SAMLEnforcementPolicy!
attributeMappings: SAMLAttributeMappingsInput
}

View File

@@ -55,6 +55,7 @@ type ResolverRoot interface {
Organization() OrganizationResolver
PersonalAPIKeyConnection() PersonalAPIKeyConnectionResolver
Query() QueryResolver
SAMLConfiguration() SAMLConfigurationResolver
SAMLConfigurationConnection() SAMLConfigurationConnectionResolver
Session() SessionResolver
SessionConnection() SessionConnectionResolver
@@ -339,7 +340,6 @@ type ComplexityRoot struct {
IdpCertificate func(childComplexity int) int
IdpEntityID func(childComplexity int) int
IdpSsoURL func(childComplexity int) int
SpMetadataURL func(childComplexity int) int
TestLoginURL func(childComplexity int) int
UpdatedAt func(childComplexity int) int
}
@@ -485,6 +485,9 @@ type QueryResolver interface {
Viewer(ctx context.Context) (*types.Identity, error)
CheckSSOAvailability(ctx context.Context, email string) (*types.SSOAvailability, error)
}
type SAMLConfigurationResolver interface {
TestLoginURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error)
}
type SAMLConfigurationConnectionResolver interface {
TotalCount(ctx context.Context, obj *types.SAMLConfigurationConnection) (*int, error)
}
@@ -1636,12 +1639,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.SAMLConfiguration.IdpSsoURL(childComplexity), true
case "SAMLConfiguration.spMetadataUrl":
if e.complexity.SAMLConfiguration.SpMetadataURL == nil {
break
}
return e.complexity.SAMLConfiguration.SpMetadataURL(childComplexity), true
case "SAMLConfiguration.testLoginUrl":
if e.complexity.SAMLConfiguration.TestLoginURL == nil {
break
@@ -2278,8 +2275,7 @@ type SAMLConfiguration implements Node {
autoSignupEnabled: Boolean!
createdAt: Datetime!
updatedAt: Datetime!
spMetadataUrl: String!
testLoginUrl: String!
testLoginUrl: String! @goField(forceResolver: true)
attributeMappings: SAMLAttributeMappings!
}
@@ -2618,7 +2614,7 @@ input UpdateSAMLConfigurationInput {
idpSsoUrl: String
idpCertificate: String
autoSignupEnabled: Boolean
enforcementPolicy: SAMLEnforcementPolicy
enforcementPolicy: SAMLEnforcementPolicy!
attributeMappings: SAMLAttributeMappingsInput
}
@@ -9532,35 +9528,6 @@ func (ec *executionContext) fieldContext_SAMLConfiguration_updatedAt(_ context.C
return fc, nil
}
func (ec *executionContext) _SAMLConfiguration_spMetadataUrl(ctx context.Context, field graphql.CollectedField, obj *types.SAMLConfiguration) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_SAMLConfiguration_spMetadataUrl,
func(ctx context.Context) (any, error) {
return obj.SpMetadataURL, nil
},
nil,
ec.marshalNString2string,
true,
true,
)
}
func (ec *executionContext) fieldContext_SAMLConfiguration_spMetadataUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "SAMLConfiguration",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _SAMLConfiguration_testLoginUrl(ctx context.Context, field graphql.CollectedField, obj *types.SAMLConfiguration) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -9568,7 +9535,7 @@ func (ec *executionContext) _SAMLConfiguration_testLoginUrl(ctx context.Context,
field,
ec.fieldContext_SAMLConfiguration_testLoginUrl,
func(ctx context.Context) (any, error) {
return obj.TestLoginURL, nil
return ec.resolvers.SAMLConfiguration().TestLoginURL(ctx, obj)
},
nil,
ec.marshalNString2string,
@@ -9581,8 +9548,8 @@ func (ec *executionContext) fieldContext_SAMLConfiguration_testLoginUrl(_ contex
fc = &graphql.FieldContext{
Object: "SAMLConfiguration",
Field: field,
IsMethod: false,
IsResolver: false,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
@@ -9778,8 +9745,6 @@ func (ec *executionContext) fieldContext_SAMLConfigurationEdge_node(_ context.Co
return ec.fieldContext_SAMLConfiguration_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_SAMLConfiguration_updatedAt(ctx, field)
case "spMetadataUrl":
return ec.fieldContext_SAMLConfiguration_spMetadataUrl(ctx, field)
case "testLoginUrl":
return ec.fieldContext_SAMLConfiguration_testLoginUrl(ctx, field)
case "attributeMappings":
@@ -10707,8 +10672,6 @@ func (ec *executionContext) fieldContext_UpdateSAMLConfigurationPayload_samlConf
return ec.fieldContext_SAMLConfiguration_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_SAMLConfiguration_updatedAt(ctx, field)
case "spMetadataUrl":
return ec.fieldContext_SAMLConfiguration_spMetadataUrl(ctx, field)
case "testLoginUrl":
return ec.fieldContext_SAMLConfiguration_testLoginUrl(ctx, field)
case "attributeMappings":
@@ -13214,7 +13177,7 @@ func (ec *executionContext) unmarshalInputUpdateSAMLConfigurationInput(ctx conte
it.AutoSignupEnabled = data
case "enforcementPolicy":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("enforcementPolicy"))
data, err := ec.unmarshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy(ctx, v)
data, err := ec.unmarshalNSAMLEnforcementPolicy2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy(ctx, v)
if err != nil {
return it, err
}
@@ -16030,17 +15993,17 @@ func (ec *executionContext) _SAMLConfiguration(ctx context.Context, sel ast.Sele
case "id":
out.Values[i] = ec._SAMLConfiguration_id(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "emailDomain":
out.Values[i] = ec._SAMLConfiguration_emailDomain(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "enforcementPolicy":
out.Values[i] = ec._SAMLConfiguration_enforcementPolicy(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "domainVerifiedAt":
out.Values[i] = ec._SAMLConfiguration_domainVerifiedAt(ctx, field, obj)
@@ -16049,47 +16012,73 @@ func (ec *executionContext) _SAMLConfiguration(ctx context.Context, sel ast.Sele
case "idpEntityId":
out.Values[i] = ec._SAMLConfiguration_idpEntityId(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "idpSsoUrl":
out.Values[i] = ec._SAMLConfiguration_idpSsoUrl(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "idpCertificate":
out.Values[i] = ec._SAMLConfiguration_idpCertificate(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "autoSignupEnabled":
out.Values[i] = ec._SAMLConfiguration_autoSignupEnabled(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "createdAt":
out.Values[i] = ec._SAMLConfiguration_createdAt(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "updatedAt":
out.Values[i] = ec._SAMLConfiguration_updatedAt(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "spMetadataUrl":
out.Values[i] = ec._SAMLConfiguration_spMetadataUrl(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
case "testLoginUrl":
out.Values[i] = ec._SAMLConfiguration_testLoginUrl(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
field := field
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._SAMLConfiguration_testLoginUrl(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&fs.Invalids, 1)
}
return res
}
if field.Deferrable != nil {
dfs, ok := deferred[field.Deferrable.Label]
di := 0
if ok {
dfs.AddField(field)
di = len(dfs.Values) - 1
} else {
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
deferred[field.Deferrable.Label] = dfs
}
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
return innerFunc(ctx, dfs)
})
// don't run the out.Concurrently() call below
out.Values[i] = graphql.Null
continue
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "attributeMappings":
out.Values[i] = ec._SAMLConfiguration_attributeMappings(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
atomic.AddUint32(&out.Invalids, 1)
}
default:
panic("unknown field " + strconv.Quote(field.Name))
@@ -18881,38 +18870,6 @@ func (ec *executionContext) marshalOSAMLConfigurationConnection2ᚖgoᚗproboᚗ
return ec._SAMLConfigurationConnection(ctx, sel, v)
}
func (ec *executionContext) unmarshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy(ctx context.Context, v any) (*coredata.SAMLEnforcementPolicy, error) {
if v == nil {
return nil, nil
}
tmp, err := graphql.UnmarshalString(v)
res := unmarshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy[tmp]
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy(ctx context.Context, sel ast.SelectionSet, v *coredata.SAMLEnforcementPolicy) graphql.Marshaler {
if v == nil {
return graphql.Null
}
_ = sel
_ = ctx
res := graphql.MarshalString(marshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy[*v])
return res
}
var (
unmarshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy = map[string]coredata.SAMLEnforcementPolicy{
"OFF": coredata.SAMLEnforcementPolicyOff,
"OPTIONAL": coredata.SAMLEnforcementPolicyOptional,
"REQUIRED": coredata.SAMLEnforcementPolicyRequired,
}
marshalOSAMLEnforcementPolicy2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐSAMLEnforcementPolicy = map[coredata.SAMLEnforcementPolicy]string{
coredata.SAMLEnforcementPolicyOff: "OFF",
coredata.SAMLEnforcementPolicyOptional: "OPTIONAL",
coredata.SAMLEnforcementPolicyRequired: "REQUIRED",
}
)
func (ec *executionContext) marshalOSession2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐSession(ctx context.Context, sel ast.SelectionSet, v *types.Session) graphql.Marshaler {
if v == nil {
return graphql.Null

View File

@@ -371,7 +371,6 @@ type SAMLConfiguration struct {
AutoSignupEnabled bool `json:"autoSignupEnabled"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
SpMetadataURL string `json:"spMetadataUrl"`
TestLoginURL string `json:"testLoginUrl"`
AttributeMappings *SAMLAttributeMappings `json:"attributeMappings"`
}
@@ -472,14 +471,14 @@ type UpdatePersonalAPIKeyPayload struct {
}
type UpdateSAMLConfigurationInput struct {
OrganizationID gid.GID `json:"organizationId"`
SamlConfigurationID gid.GID `json:"samlConfigurationId"`
IdpEntityID *string `json:"idpEntityId,omitempty"`
IdpSsoURL *string `json:"idpSsoUrl,omitempty"`
IdpCertificate *string `json:"idpCertificate,omitempty"`
AutoSignupEnabled *bool `json:"autoSignupEnabled,omitempty"`
EnforcementPolicy *coredata.SAMLEnforcementPolicy `json:"enforcementPolicy,omitempty"`
AttributeMappings *SAMLAttributeMappingsInput `json:"attributeMappings,omitempty"`
OrganizationID gid.GID `json:"organizationId"`
SamlConfigurationID gid.GID `json:"samlConfigurationId"`
IdpEntityID *string `json:"idpEntityId,omitempty"`
IdpSsoURL *string `json:"idpSsoUrl,omitempty"`
IdpCertificate *string `json:"idpCertificate,omitempty"`
AutoSignupEnabled *bool `json:"autoSignupEnabled,omitempty"`
EnforcementPolicy coredata.SAMLEnforcementPolicy `json:"enforcementPolicy"`
AttributeMappings *SAMLAttributeMappingsInput `json:"attributeMappings,omitempty"`
}
type UpdateSAMLConfigurationPayload struct {

View File

@@ -9,6 +9,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/99designs/gqlgen/graphql"
@@ -933,6 +934,7 @@ func (r *mutationResolver) UpdateSAMLConfiguration(ctx context.Context, input ty
IdPSsoURL: input.IdpSsoURL,
IdPCertificate: input.IdpCertificate,
AutoSignupEnabled: input.AutoSignupEnabled,
EnforcementPolicy: &input.EnforcementPolicy,
}
if input.AttributeMappings != nil {
@@ -1163,6 +1165,16 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewInvitation(invitation), nil
}
case coredata.SAMLConfigurationEntityType:
action = iam.ActionIAMSAMLConfigurationGet
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
}
default:
return nil, fmt.Errorf("unsupported entity type: %d", id.EntityType())
}
@@ -1231,6 +1243,17 @@ func (r *queryResolver) CheckSSOAvailability(ctx context.Context, email string)
panic(fmt.Errorf("not implemented: CheckSSOAvailability - checkSSOAvailability"))
}
// TestLoginURL is the resolver for the testLoginUrl field.
func (r *sAMLConfigurationResolver) TestLoginURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error) {
entityID := r.iam.SAMLService.GetEntityID()
parts := strings.Split(entityID, "/connect/saml/metadata")
if len(parts) != 2 {
return "", fmt.Errorf("invalid entity ID format")
}
return fmt.Sprintf("%s/connect/saml/login/%s", parts[0], obj.ID), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *sAMLConfigurationConnectionResolver) TotalCount(ctx context.Context, obj *types.SAMLConfigurationConnection) (*int, error) {
switch obj.Resolver.(type) {
@@ -1314,6 +1337,11 @@ func (r *Resolver) PersonalAPIKeyConnection() schema.PersonalAPIKeyConnectionRes
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
// SAMLConfiguration returns schema.SAMLConfigurationResolver implementation.
func (r *Resolver) SAMLConfiguration() schema.SAMLConfigurationResolver {
return &sAMLConfigurationResolver{r}
}
// SAMLConfigurationConnection returns schema.SAMLConfigurationConnectionResolver implementation.
func (r *Resolver) SAMLConfigurationConnection() schema.SAMLConfigurationConnectionResolver {
return &sAMLConfigurationConnectionResolver{r}
@@ -1336,6 +1364,7 @@ type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type personalAPIKeyConnectionResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
type sAMLConfigurationResolver struct{ *Resolver }
type sAMLConfigurationConnectionResolver struct{ *Resolver }
type sessionResolver struct{ *Resolver }
type sessionConnectionResolver struct{ *Resolver }