mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:47:33 +00:00
chore(oidc): remove legacy storage methods (#10061)
# Which Problems Are Solved Stabilize the optimized introspection code and cleanup unused code. # How the Problems Are Solved - `oidc_legacy_introspection` feature flag is removed and reserved. - `OPStorage` which are no longer needed have their bodies removed. - The method definitions need to remain in place so the interface remains implemented. - A panic is thrown in case any such method is still called # Additional Changes - A number of `OPStorage` methods related to token creation were already unused. These are also cleaned up. # Additional Context - Closes #10027 - #7822 --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
@@ -20,7 +20,6 @@ func systemFeaturesToCommand(req *feature_pb.SetSystemFeaturesRequest) (*command
|
||||
return &command.SystemFeatures{
|
||||
LoginDefaultOrg: req.LoginDefaultOrg,
|
||||
TriggerIntrospectionProjections: req.OidcTriggerIntrospectionProjections,
|
||||
LegacyIntrospection: req.OidcLegacyIntrospection,
|
||||
UserSchema: req.UserSchema,
|
||||
TokenExchange: req.OidcTokenExchange,
|
||||
ImprovedPerformance: improvedPerformanceListToDomain(req.ImprovedPerformance),
|
||||
@@ -37,7 +36,6 @@ func systemFeaturesToPb(f *query.SystemFeatures) *feature_pb.GetSystemFeaturesRe
|
||||
Details: object.DomainToDetailsPb(f.Details),
|
||||
LoginDefaultOrg: featureSourceToFlagPb(&f.LoginDefaultOrg),
|
||||
OidcTriggerIntrospectionProjections: featureSourceToFlagPb(&f.TriggerIntrospectionProjections),
|
||||
OidcLegacyIntrospection: featureSourceToFlagPb(&f.LegacyIntrospection),
|
||||
UserSchema: featureSourceToFlagPb(&f.UserSchema),
|
||||
OidcTokenExchange: featureSourceToFlagPb(&f.TokenExchange),
|
||||
ImprovedPerformance: featureSourceToImprovedPerformanceFlagPb(&f.ImprovedPerformance),
|
||||
@@ -57,7 +55,6 @@ func instanceFeaturesToCommand(req *feature_pb.SetInstanceFeaturesRequest) (*com
|
||||
return &command.InstanceFeatures{
|
||||
LoginDefaultOrg: req.LoginDefaultOrg,
|
||||
TriggerIntrospectionProjections: req.OidcTriggerIntrospectionProjections,
|
||||
LegacyIntrospection: req.OidcLegacyIntrospection,
|
||||
UserSchema: req.UserSchema,
|
||||
TokenExchange: req.OidcTokenExchange,
|
||||
ImprovedPerformance: improvedPerformanceListToDomain(req.ImprovedPerformance),
|
||||
@@ -77,7 +74,6 @@ func instanceFeaturesToPb(f *query.InstanceFeatures) *feature_pb.GetInstanceFeat
|
||||
Details: object.DomainToDetailsPb(f.Details),
|
||||
LoginDefaultOrg: featureSourceToFlagPb(&f.LoginDefaultOrg),
|
||||
OidcTriggerIntrospectionProjections: featureSourceToFlagPb(&f.TriggerIntrospectionProjections),
|
||||
OidcLegacyIntrospection: featureSourceToFlagPb(&f.LegacyIntrospection),
|
||||
UserSchema: featureSourceToFlagPb(&f.UserSchema),
|
||||
OidcTokenExchange: featureSourceToFlagPb(&f.TokenExchange),
|
||||
ImprovedPerformance: featureSourceToImprovedPerformanceFlagPb(&f.ImprovedPerformance),
|
||||
|
@@ -21,7 +21,6 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
arg := &feature_pb.SetSystemFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
OidcTriggerIntrospectionProjections: gu.Ptr(false),
|
||||
OidcLegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
OidcTokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -34,7 +33,6 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
want := &command.SystemFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
TokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -64,10 +62,6 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
LegacyIntrospection: query.FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
UserSchema: query.FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
@@ -114,10 +108,6 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature_pb.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
UserSchema: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
@@ -160,7 +150,6 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
arg := &feature_pb.SetInstanceFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
OidcTriggerIntrospectionProjections: gu.Ptr(false),
|
||||
OidcLegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
OidcTokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -177,7 +166,6 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
want := &command.InstanceFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
TokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -211,10 +199,6 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
LegacyIntrospection: query.FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
UserSchema: query.FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
@@ -269,10 +253,6 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature_pb.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
UserSchema: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
|
@@ -209,7 +209,6 @@ func TestServer_GetSystemFeatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assertFeatureFlag(t, tt.want.LoginDefaultOrg, got.LoginDefaultOrg)
|
||||
assertFeatureFlag(t, tt.want.OidcTriggerIntrospectionProjections, got.OidcTriggerIntrospectionProjections)
|
||||
assertFeatureFlag(t, tt.want.OidcLegacyIntrospection, got.OidcLegacyIntrospection)
|
||||
assertFeatureFlag(t, tt.want.UserSchema, got.UserSchema)
|
||||
})
|
||||
}
|
||||
@@ -321,7 +320,7 @@ func TestServer_ResetInstanceFeatures(t *testing.T) {
|
||||
|
||||
func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
_, err := Client.SetSystemFeatures(SystemCTX, &feature.SetSystemFeaturesRequest{
|
||||
OidcLegacyIntrospection: gu.Ptr(true),
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
@@ -358,17 +357,13 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
},
|
||||
want: &feature.GetInstanceFeaturesResponse{
|
||||
LoginDefaultOrg: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
OidcTriggerIntrospectionProjections: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
UserSchema: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
@@ -427,10 +422,6 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
UserSchema: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
@@ -456,7 +447,6 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assertFeatureFlag(t, tt.want.LoginDefaultOrg, got.LoginDefaultOrg)
|
||||
assertFeatureFlag(t, tt.want.OidcTriggerIntrospectionProjections, got.OidcTriggerIntrospectionProjections)
|
||||
assertFeatureFlag(t, tt.want.OidcLegacyIntrospection, got.OidcLegacyIntrospection)
|
||||
assertFeatureFlag(t, tt.want.UserSchema, got.UserSchema)
|
||||
})
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@ func systemFeaturesToCommand(req *feature_pb.SetSystemFeaturesRequest) *command.
|
||||
return &command.SystemFeatures{
|
||||
LoginDefaultOrg: req.LoginDefaultOrg,
|
||||
TriggerIntrospectionProjections: req.OidcTriggerIntrospectionProjections,
|
||||
LegacyIntrospection: req.OidcLegacyIntrospection,
|
||||
UserSchema: req.UserSchema,
|
||||
TokenExchange: req.OidcTokenExchange,
|
||||
ImprovedPerformance: improvedPerformanceListToDomain(req.ImprovedPerformance),
|
||||
@@ -25,7 +24,6 @@ func systemFeaturesToPb(f *query.SystemFeatures) *feature_pb.GetSystemFeaturesRe
|
||||
Details: object.DomainToDetailsPb(f.Details),
|
||||
LoginDefaultOrg: featureSourceToFlagPb(&f.LoginDefaultOrg),
|
||||
OidcTriggerIntrospectionProjections: featureSourceToFlagPb(&f.TriggerIntrospectionProjections),
|
||||
OidcLegacyIntrospection: featureSourceToFlagPb(&f.LegacyIntrospection),
|
||||
UserSchema: featureSourceToFlagPb(&f.UserSchema),
|
||||
OidcTokenExchange: featureSourceToFlagPb(&f.TokenExchange),
|
||||
ImprovedPerformance: featureSourceToImprovedPerformanceFlagPb(&f.ImprovedPerformance),
|
||||
@@ -37,7 +35,6 @@ func instanceFeaturesToCommand(req *feature_pb.SetInstanceFeaturesRequest) *comm
|
||||
return &command.InstanceFeatures{
|
||||
LoginDefaultOrg: req.LoginDefaultOrg,
|
||||
TriggerIntrospectionProjections: req.OidcTriggerIntrospectionProjections,
|
||||
LegacyIntrospection: req.OidcLegacyIntrospection,
|
||||
UserSchema: req.UserSchema,
|
||||
TokenExchange: req.OidcTokenExchange,
|
||||
ImprovedPerformance: improvedPerformanceListToDomain(req.ImprovedPerformance),
|
||||
@@ -52,7 +49,6 @@ func instanceFeaturesToPb(f *query.InstanceFeatures) *feature_pb.GetInstanceFeat
|
||||
Details: object.DomainToDetailsPb(f.Details),
|
||||
LoginDefaultOrg: featureSourceToFlagPb(&f.LoginDefaultOrg),
|
||||
OidcTriggerIntrospectionProjections: featureSourceToFlagPb(&f.TriggerIntrospectionProjections),
|
||||
OidcLegacyIntrospection: featureSourceToFlagPb(&f.LegacyIntrospection),
|
||||
UserSchema: featureSourceToFlagPb(&f.UserSchema),
|
||||
OidcTokenExchange: featureSourceToFlagPb(&f.TokenExchange),
|
||||
ImprovedPerformance: featureSourceToImprovedPerformanceFlagPb(&f.ImprovedPerformance),
|
||||
|
@@ -20,7 +20,6 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
arg := &feature_pb.SetSystemFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
OidcTriggerIntrospectionProjections: gu.Ptr(false),
|
||||
OidcLegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
OidcTokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -29,7 +28,6 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
want := &command.SystemFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
TokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -54,10 +52,6 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
LegacyIntrospection: query.FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
UserSchema: query.FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
@@ -89,10 +83,6 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature_pb.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
UserSchema: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
@@ -118,7 +108,6 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
arg := &feature_pb.SetInstanceFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
OidcTriggerIntrospectionProjections: gu.Ptr(false),
|
||||
OidcLegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
OidcTokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -128,7 +117,6 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
want := &command.InstanceFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: nil,
|
||||
UserSchema: gu.Ptr(true),
|
||||
TokenExchange: gu.Ptr(true),
|
||||
ImprovedPerformance: nil,
|
||||
@@ -154,10 +142,6 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
LegacyIntrospection: query.FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
UserSchema: query.FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
@@ -193,10 +177,6 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature_pb.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
UserSchema: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
|
@@ -194,10 +194,6 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
UserSchema: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
@@ -256,10 +252,6 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
OidcLegacyIntrospection: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
UserSchema: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
@@ -285,7 +277,6 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assertFeatureFlag(t, tt.want.LoginDefaultOrg, got.LoginDefaultOrg)
|
||||
assertFeatureFlag(t, tt.want.OidcTriggerIntrospectionProjections, got.OidcTriggerIntrospectionProjections)
|
||||
assertFeatureFlag(t, tt.want.OidcLegacyIntrospection, got.OidcLegacyIntrospection)
|
||||
assertFeatureFlag(t, tt.want.UserSchema, got.UserSchema)
|
||||
})
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/domain/federatedlogout"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/user/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@@ -216,11 +215,11 @@ func (o *OPStorage) SaveAuthCode(ctx context.Context, id, code string) (err erro
|
||||
return o.repo.SaveAuthCode(ctx, id, code, userAgentID)
|
||||
}
|
||||
|
||||
func (o *OPStorage) DeleteAuthRequest(ctx context.Context, id string) (err error) {
|
||||
func (o *OPStorage) DeleteAuthRequest(context.Context, string) error {
|
||||
panic(o.panicErr("DeleteAuthRequest"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) CreateAccessToken(ctx context.Context, req op.TokenRequest) (string, time.Time, error) {
|
||||
func (o *OPStorage) CreateAccessToken(context.Context, op.TokenRequest) (string, time.Time, error) {
|
||||
panic(o.panicErr("CreateAccessToken"))
|
||||
}
|
||||
|
||||
@@ -492,34 +491,6 @@ func (o *OPStorage) GetRefreshTokenInfo(ctx context.Context, clientID string, to
|
||||
return refreshToken.UserID, refreshToken.ID, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertProjectRoleScopes(ctx context.Context, clientID string, scopes []string) ([]string, error) {
|
||||
for _, scope := range scopes {
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
return scopes, nil
|
||||
}
|
||||
}
|
||||
|
||||
project, err := o.query.ProjectByOIDCClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "OIDC-w4wIn", "Errors.Internal")
|
||||
}
|
||||
if !project.ProjectRoleAssertion {
|
||||
return scopes, nil
|
||||
}
|
||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(project.ID)
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
||||
}
|
||||
roles, err := o.query.SearchProjectRoles(ctx, true, &query.ProjectRoleSearchQueries{Queries: []query.SearchQuery{projectIDQuery}}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, role := range roles.ProjectRoles {
|
||||
scopes = append(scopes, ScopeProjectRolePrefix+role.Key)
|
||||
}
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertProjectRoleScopesByProject(ctx context.Context, project *query.Project, scopes []string) ([]string, error) {
|
||||
for _, scope := range scopes {
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
@@ -543,22 +514,6 @@ func (o *OPStorage) assertProjectRoleScopesByProject(ctx context.Context, projec
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertClientScopesForPAT(ctx context.Context, token *model.TokenView, clientID, projectID string) error {
|
||||
token.Audience = append(token.Audience, clientID)
|
||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(projectID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
||||
}
|
||||
roles, err := o.query.SearchProjectRoles(ctx, true, &query.ProjectRoleSearchQueries{Queries: []query.SearchQuery{projectIDQuery}}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, role := range roles.ProjectRoles {
|
||||
token.Scopes = append(token.Scopes, ScopeProjectRolePrefix+role.Key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setContextUserSystem(ctx context.Context) context.Context {
|
||||
data := authz.CtxData{
|
||||
UserID: "SYSTEM",
|
||||
|
@@ -2,25 +2,17 @@ package oidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/go-jose/go-jose/v4"
|
||||
"github.com/zitadel/logging"
|
||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||
"github.com/zitadel/oidc/v3/pkg/op"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/actions"
|
||||
"github.com/zitadel/zitadel/internal/actions/object"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
api_http "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
@@ -44,6 +36,9 @@ const (
|
||||
oidcCtx = "oidc"
|
||||
)
|
||||
|
||||
// GetClientByClientID implements the op.Storage interface to retrieve an OIDC client by its ID.
|
||||
//
|
||||
// TODO: Still used for Auth request creation for v1 login.
|
||||
func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Client, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
@@ -57,819 +52,44 @@ func (o *OPStorage) GetClientByClientID(ctx context.Context, id string) (_ op.Cl
|
||||
return ClientFromBusiness(client, o.defaultLoginURL, o.defaultLoginURLV2), nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) GetKeyByIDAndClientID(ctx context.Context, keyID, userID string) (_ *jose.JSONWebKey, err error) {
|
||||
return o.GetKeyByIDAndIssuer(ctx, keyID, userID)
|
||||
func (o *OPStorage) GetKeyByIDAndClientID(context.Context, string, string) (*jose.JSONWebKey, error) {
|
||||
panic(o.panicErr("GetKeyByIDAndClientID"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) GetKeyByIDAndIssuer(ctx context.Context, keyID, issuer string) (_ *jose.JSONWebKey, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
publicKeyData, err := o.query.GetAuthNKeyPublicKeyByIDAndIdentifier(ctx, keyID, issuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
publicKey, err := crypto.BytesToPublicKey(publicKeyData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &jose.JSONWebKey{
|
||||
KeyID: keyID,
|
||||
Use: "sig",
|
||||
Key: publicKey,
|
||||
}, nil
|
||||
func (o *OPStorage) ValidateJWTProfileScopes(context.Context, string, []string) ([]string, error) {
|
||||
panic(o.panicErr("ValidateJWTProfileScopes"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string, scopes []string) (_ []string, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
user, err := o.query.GetUserByID(ctx, true, subject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return o.checkOrgScopes(ctx, user, scopes)
|
||||
func (o *OPStorage) AuthorizeClientIDSecret(context.Context, string, string) error {
|
||||
panic(o.panicErr("AuthorizeClientIDSecret"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
ctx = authz.SetCtxData(ctx, authz.CtxData{
|
||||
UserID: oidcCtx,
|
||||
OrgID: oidcCtx,
|
||||
})
|
||||
app, err := o.query.AppByClientID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if app.OIDCConfig != nil {
|
||||
return o.command.VerifyOIDCClientSecret(ctx, app.ProjectID, app.ID, secret)
|
||||
}
|
||||
return o.command.VerifyAPIClientSecret(ctx, app.ProjectID, app.ID, secret)
|
||||
func (o *OPStorage) SetUserinfoFromToken(context.Context, *oidc.UserInfo, string, string, string) error {
|
||||
panic(o.panicErr("SetUserinfoFromToken"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo *oidc.UserInfo, tokenID, subject, origin string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
|
||||
if strings.HasPrefix(tokenID, command.IDPrefixV2) {
|
||||
token, err := o.query.ActiveAccessTokenByToken(ctx, tokenID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = o.isOriginAllowed(ctx, token.ClientID, origin); err != nil {
|
||||
return err
|
||||
}
|
||||
return o.setUserinfo(ctx, userInfo, token.UserID, token.ClientID, token.Scope, nil)
|
||||
}
|
||||
|
||||
token, err := o.repo.TokenByIDs(ctx, subject, tokenID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
||||
}
|
||||
if token.ApplicationID != "" {
|
||||
if err = o.isOriginAllowed(ctx, token.ApplicationID, origin); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return o.setUserinfo(ctx, userInfo, token.UserID, token.ApplicationID, token.Scopes, nil)
|
||||
func (o *OPStorage) SetUserinfoFromScopes(context.Context, *oidc.UserInfo, string, string, []string) error {
|
||||
panic(o.panicErr("SetUserinfoFromScopes"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo *oidc.UserInfo, userID, applicationID string, scopes []string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
if applicationID != "" {
|
||||
app, err := o.query.AppByOIDCClientID(ctx, applicationID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if app.OIDCConfig.AssertIDTokenRole {
|
||||
scopes, err = o.assertProjectRoleScopes(ctx, applicationID, scopes)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPreconditionFailed(err, "OIDC-Dfe2s", "Errors.Internal")
|
||||
}
|
||||
}
|
||||
}
|
||||
return o.setUserinfo(ctx, userInfo, userID, applicationID, scopes, nil)
|
||||
func (o *OPStorage) SetUserinfoFromRequest(context.Context, *oidc.UserInfo, op.IDTokenRequest, []string) error {
|
||||
panic(o.panicErr("SetUserinfoFromRequest"))
|
||||
}
|
||||
|
||||
// SetUserinfoFromRequest extends the SetUserinfoFromScopes during the id_token generation.
|
||||
// This is required for V2 tokens to be able to set the sessionID (`sid`) claim.
|
||||
func (o *OPStorage) SetUserinfoFromRequest(ctx context.Context, userinfo *oidc.UserInfo, request op.IDTokenRequest, _ []string) error {
|
||||
switch t := request.(type) {
|
||||
case *AuthRequestV2:
|
||||
userinfo.AppendClaims("sid", t.SessionID)
|
||||
case *RefreshTokenRequestV2:
|
||||
userinfo.AppendClaims("sid", t.SessionID)
|
||||
}
|
||||
return nil
|
||||
func (o *OPStorage) SetIntrospectionFromToken(context.Context, *oidc.IntrospectionResponse, string, string, string) error {
|
||||
panic(o.panicErr("SetIntrospectionFromToken"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection *oidc.IntrospectionResponse, tokenID, subject, clientID string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
|
||||
if strings.HasPrefix(tokenID, command.IDPrefixV2) {
|
||||
token, err := o.query.ActiveAccessTokenByToken(ctx, tokenID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
projectID, err := o.query.ProjectIDFromClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
|
||||
}
|
||||
return o.introspect(ctx, introspection,
|
||||
tokenID, token.UserID, token.ClientID, clientID, projectID,
|
||||
token.Audience, token.Scope,
|
||||
token.AccessTokenCreation, token.AccessTokenExpiration)
|
||||
}
|
||||
|
||||
token, err := o.repo.TokenByIDs(ctx, subject, tokenID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
||||
}
|
||||
projectID, err := o.query.ProjectIDFromClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
|
||||
}
|
||||
if token.IsPAT {
|
||||
err = o.assertClientScopesForPAT(ctx, token, clientID, projectID)
|
||||
if err != nil {
|
||||
return zerrors.ThrowPreconditionFailed(err, "OIDC-AGefw", "Errors.Internal")
|
||||
}
|
||||
}
|
||||
return o.introspect(ctx, introspection,
|
||||
token.ID, token.UserID, token.ApplicationID, clientID, projectID,
|
||||
token.Audience, token.Scopes,
|
||||
token.CreationDate, token.Expiration)
|
||||
func (o *OPStorage) ClientCredentialsTokenRequest(context.Context, string, []string) (op.TokenRequest, error) {
|
||||
panic(o.panicErr("ClientCredentialsTokenRequest"))
|
||||
}
|
||||
|
||||
func (o *OPStorage) ClientCredentialsTokenRequest(ctx context.Context, clientID string, scope []string) (_ op.TokenRequest, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
user, err := o.query.GetUserByLoginName(ctx, false, clientID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scope, err = o.checkOrgScopes(ctx, user, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
audience := domain.AddAudScopeToAudience(ctx, nil, scope)
|
||||
return &clientCredentialsRequest{
|
||||
sub: user.ID,
|
||||
scopes: scope,
|
||||
audience: audience,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ClientCredentials method is kept to keep the storage interface implemented.
|
||||
// However, it should never be called as the VerifyClient method on the Server is overridden.
|
||||
func (o *OPStorage) ClientCredentials(context.Context, string, string) (op.Client, error) {
|
||||
return nil, zerrors.ThrowInternal(nil, "OIDC-Su8So", "Errors.Internal")
|
||||
panic(o.panicErr("ClientCredentials"))
|
||||
}
|
||||
|
||||
// isOriginAllowed checks whether a call by the client to the endpoint is allowed from the provided origin
|
||||
// if no origin is provided, no error will be returned
|
||||
func (o *OPStorage) isOriginAllowed(ctx context.Context, clientID, origin string) error {
|
||||
if origin == "" {
|
||||
return nil
|
||||
}
|
||||
app, err := o.query.AppByOIDCClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if api_http.IsOriginAllowed(app.OIDCConfig.AllowedOrigins, origin) {
|
||||
return nil
|
||||
}
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
|
||||
}
|
||||
|
||||
func (o *OPStorage) introspect(
|
||||
ctx context.Context,
|
||||
introspection *oidc.IntrospectionResponse,
|
||||
tokenID, subject, tokenClientID, introspectionClientID, introspectionProjectID string,
|
||||
audience, scope []string,
|
||||
tokenCreation, tokenExpiration time.Time,
|
||||
) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
for _, aud := range audience {
|
||||
if aud == introspectionClientID || aud == introspectionProjectID {
|
||||
userInfo := new(oidc.UserInfo)
|
||||
err = o.setUserinfo(ctx, userInfo, subject, introspectionClientID, scope, []string{introspectionProjectID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
introspection.SetUserInfo(userInfo)
|
||||
introspection.Scope = scope
|
||||
introspection.ClientID = tokenClientID
|
||||
introspection.TokenType = oidc.BearerToken
|
||||
introspection.Expiration = oidc.FromTime(tokenExpiration)
|
||||
introspection.IssuedAt = oidc.FromTime(tokenCreation)
|
||||
introspection.NotBefore = oidc.FromTime(tokenCreation)
|
||||
introspection.Audience = audience
|
||||
introspection.Issuer = op.IssuerFromContext(ctx)
|
||||
introspection.JWTID = tokenID
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return zerrors.ThrowPermissionDenied(nil, "OIDC-sdg3G", "token is not valid for this client")
|
||||
}
|
||||
|
||||
func (o *OPStorage) checkOrgScopes(ctx context.Context, user *query.User, scopes []string) ([]string, error) {
|
||||
for i := len(scopes) - 1; i >= 0; i-- {
|
||||
scope := scopes[i]
|
||||
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
|
||||
var orgID string
|
||||
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
if err == nil {
|
||||
orgID = org.ID
|
||||
}
|
||||
if orgID != user.ResourceOwner {
|
||||
scopes[i] = scopes[len(scopes)-1]
|
||||
scopes[len(scopes)-1] = ""
|
||||
scopes = scopes[:len(scopes)-1]
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(scope, domain.OrgIDScope) {
|
||||
if strings.TrimPrefix(scope, domain.OrgIDScope) != user.ResourceOwner {
|
||||
scopes[i] = scopes[len(scopes)-1]
|
||||
scopes[len(scopes)-1] = ""
|
||||
scopes = scopes[:len(scopes)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) setUserinfo(ctx context.Context, userInfo *oidc.UserInfo, userID, applicationID string, scopes []string, roleAudience []string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
user, err := o.query.GetUserByID(ctx, true, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user.State != domain.UserStateActive {
|
||||
return zerrors.ThrowUnauthenticated(nil, "OIDC-S3tha", "Errors.Users.NotActive")
|
||||
}
|
||||
var allRoles bool
|
||||
roles := make([]string, 0)
|
||||
for _, scope := range scopes {
|
||||
switch scope {
|
||||
case oidc.ScopeOpenID:
|
||||
userInfo.Subject = user.ID
|
||||
case oidc.ScopeEmail:
|
||||
setUserInfoEmail(userInfo, user)
|
||||
case oidc.ScopeProfile:
|
||||
o.setUserInfoProfile(ctx, userInfo, user)
|
||||
case oidc.ScopePhone:
|
||||
setUserInfoPhone(userInfo, user)
|
||||
case oidc.ScopeAddress:
|
||||
//TODO: handle address for human users as soon as implemented
|
||||
case ScopeUserMetaData:
|
||||
if err := o.setUserInfoMetadata(ctx, userInfo, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
case ScopeResourceOwner:
|
||||
if err := o.setUserInfoResourceOwner(ctx, userInfo, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
case ScopeProjectsRoles:
|
||||
allRoles = true
|
||||
default:
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
|
||||
}
|
||||
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
|
||||
userInfo.AppendClaims(domain.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
}
|
||||
if strings.HasPrefix(scope, domain.OrgIDScope) {
|
||||
userInfo.AppendClaims(domain.OrgIDClaim, strings.TrimPrefix(scope, domain.OrgIDScope))
|
||||
if err := o.setUserInfoResourceOwner(ctx, userInfo, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if all roles are requested take the audience for those from the scopes
|
||||
if allRoles && len(roleAudience) == 0 {
|
||||
roleAudience = domain.AddAudScopeToAudience(ctx, roleAudience, scopes)
|
||||
}
|
||||
|
||||
userGrants, projectRoles, err := o.assertRoles(ctx, userID, applicationID, roles, roleAudience)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.setUserInfoRoleClaims(userInfo, projectRoles)
|
||||
|
||||
return o.userinfoFlows(ctx, user, userGrants, userInfo)
|
||||
}
|
||||
|
||||
func (o *OPStorage) setUserInfoProfile(ctx context.Context, userInfo *oidc.UserInfo, user *query.User) {
|
||||
userInfo.PreferredUsername = user.PreferredLoginName
|
||||
userInfo.UpdatedAt = oidc.FromTime(user.ChangeDate)
|
||||
if user.Machine != nil {
|
||||
userInfo.Name = user.Machine.Name
|
||||
return
|
||||
}
|
||||
userInfo.Name = user.Human.DisplayName
|
||||
userInfo.FamilyName = user.Human.LastName
|
||||
userInfo.GivenName = user.Human.FirstName
|
||||
userInfo.Nickname = user.Human.NickName
|
||||
userInfo.Gender = getGender(user.Human.Gender)
|
||||
userInfo.Locale = oidc.NewLocale(user.Human.PreferredLanguage)
|
||||
userInfo.Picture = domain.AvatarURL(o.assetAPIPrefix(ctx), user.ResourceOwner, user.Human.AvatarKey)
|
||||
}
|
||||
|
||||
func setUserInfoEmail(userInfo *oidc.UserInfo, user *query.User) {
|
||||
if user.Human == nil {
|
||||
return
|
||||
}
|
||||
userInfo.UserInfoEmail = oidc.UserInfoEmail{
|
||||
Email: string(user.Human.Email),
|
||||
EmailVerified: oidc.Bool(user.Human.IsEmailVerified)}
|
||||
}
|
||||
|
||||
func setUserInfoPhone(userInfo *oidc.UserInfo, user *query.User) {
|
||||
if user.Human == nil {
|
||||
return
|
||||
}
|
||||
userInfo.UserInfoPhone = oidc.UserInfoPhone{
|
||||
PhoneNumber: string(user.Human.Phone),
|
||||
PhoneNumberVerified: user.Human.IsPhoneVerified,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OPStorage) setUserInfoMetadata(ctx context.Context, userInfo *oidc.UserInfo, userID string) error {
|
||||
userMetaData, err := o.assertUserMetaData(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(userMetaData) > 0 {
|
||||
userInfo.AppendClaims(ClaimUserMetaData, userMetaData)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) setUserInfoResourceOwner(ctx context.Context, userInfo *oidc.UserInfo, userID string) error {
|
||||
resourceOwnerClaims, err := o.assertUserResourceOwner(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for claim, value := range resourceOwnerClaims {
|
||||
userInfo.AppendClaims(claim, value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) setUserInfoRoleClaims(userInfo *oidc.UserInfo, roles *projectsRoles) {
|
||||
if roles != nil && len(roles.projects) > 0 {
|
||||
if roles, ok := roles.projects[roles.requestProjectID]; ok {
|
||||
userInfo.AppendClaims(ClaimProjectRoles, roles)
|
||||
}
|
||||
for projectID, roles := range roles.projects {
|
||||
userInfo.AppendClaims(fmt.Sprintf(ClaimProjectRolesFormat, projectID), roles)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OPStorage) userinfoFlows(ctx context.Context, user *query.User, userGrants *query.UserGrants, userInfo *oidc.UserInfo) error {
|
||||
queriedActions, err := o.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeCustomiseToken, domain.TriggerTypePreUserinfoCreation, user.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctxFields := actions.SetContextFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("claims", userinfoClaims(userInfo)),
|
||||
actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
return object.UserFromQuery(c, user)
|
||||
}
|
||||
}),
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} {
|
||||
return func(goja.FunctionCall) goja.Value {
|
||||
resourceOwnerQuery, err := query.NewUserMetadataResourceOwnerSearchQuery(user.ResourceOwner)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to create search query")
|
||||
panic(err)
|
||||
}
|
||||
metadata, err := o.query.SearchUserMetadata(
|
||||
ctx,
|
||||
true,
|
||||
userInfo.Subject,
|
||||
&query.UserMetadataSearchQueries{Queries: []query.SearchQuery{resourceOwnerQuery}},
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
logging.WithError(err).Info("unable to get md in action")
|
||||
panic(err)
|
||||
}
|
||||
return object.UserMetadataListFromQuery(c, metadata)
|
||||
}
|
||||
}),
|
||||
actions.SetFields("grants",
|
||||
func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserGrantsFromQuery(ctx, o.query, c, userGrants)
|
||||
},
|
||||
),
|
||||
),
|
||||
actions.SetFields("org",
|
||||
actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} {
|
||||
return func(goja.FunctionCall) goja.Value {
|
||||
return object.GetOrganizationMetadata(ctx, o.query, c, user.ResourceOwner)
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
for _, action := range queriedActions {
|
||||
actionCtx, cancel := context.WithTimeout(ctx, action.Timeout())
|
||||
claimLogs := []string{}
|
||||
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("userinfo",
|
||||
actions.SetFields("setClaim", func(key string, value interface{}) {
|
||||
if strings.HasPrefix(key, ClaimPrefix) {
|
||||
return
|
||||
}
|
||||
if userInfo.Claims[key] == nil {
|
||||
userInfo.AppendClaims(key, value)
|
||||
return
|
||||
}
|
||||
claimLogs = append(claimLogs, fmt.Sprintf("key %q already exists", key))
|
||||
}),
|
||||
actions.SetFields("appendLogIntoClaims", func(entry string) {
|
||||
claimLogs = append(claimLogs, entry)
|
||||
}),
|
||||
),
|
||||
actions.SetFields("claims",
|
||||
actions.SetFields("setClaim", func(key string, value interface{}) {
|
||||
if strings.HasPrefix(key, ClaimPrefix) {
|
||||
return
|
||||
}
|
||||
if userInfo.Claims[key] == nil {
|
||||
userInfo.AppendClaims(key, value)
|
||||
return
|
||||
}
|
||||
claimLogs = append(claimLogs, fmt.Sprintf("key %q already exists", key))
|
||||
}),
|
||||
actions.SetFields("appendLogIntoClaims", func(entry string) {
|
||||
claimLogs = append(claimLogs, entry)
|
||||
}),
|
||||
),
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("setMetadata", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) != 2 {
|
||||
panic("exactly 2 (key, value) arguments expected")
|
||||
}
|
||||
key := call.Arguments[0].Export().(string)
|
||||
val := call.Arguments[1].Export()
|
||||
|
||||
value, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to marshal")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
metadata := &domain.Metadata{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
if _, err = o.command.SetUserMetadata(ctx, metadata, userInfo.Subject, user.ResourceOwner); err != nil {
|
||||
logging.WithError(err).Info("unable to set md in action")
|
||||
panic(err)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
err = actions.Run(
|
||||
actionCtx,
|
||||
ctxFields,
|
||||
apiFields,
|
||||
action.Script,
|
||||
action.Name,
|
||||
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||
)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(claimLogs) > 0 {
|
||||
userInfo.AppendClaims(fmt.Sprintf(ClaimActionLogFormat, action.Name), claimLogs)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clientID string, scopes []string) (claims map[string]interface{}, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
|
||||
roles := make([]string, 0)
|
||||
var allRoles bool
|
||||
for _, scope := range scopes {
|
||||
switch scope {
|
||||
case ScopeUserMetaData:
|
||||
userMetaData, err := o.assertUserMetaData(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(userMetaData) > 0 {
|
||||
claims = appendClaim(claims, ClaimUserMetaData, userMetaData)
|
||||
}
|
||||
case ScopeResourceOwner:
|
||||
resourceOwnerClaims, err := o.assertUserResourceOwner(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for claim, value := range resourceOwnerClaims {
|
||||
claims = appendClaim(claims, claim, value)
|
||||
}
|
||||
case ScopeProjectsRoles:
|
||||
allRoles = true
|
||||
}
|
||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||
roles = append(roles, strings.TrimPrefix(scope, ScopeProjectRolePrefix))
|
||||
}
|
||||
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
|
||||
claims = appendClaim(claims, domain.OrgDomainPrimaryClaim, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
}
|
||||
if strings.HasPrefix(scope, domain.OrgIDScope) {
|
||||
claims = appendClaim(claims, domain.OrgIDClaim, strings.TrimPrefix(scope, domain.OrgIDScope))
|
||||
resourceOwnerClaims, err := o.assertUserResourceOwner(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for claim, value := range resourceOwnerClaims {
|
||||
claims = appendClaim(claims, claim, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If requested, use the audience as context for the roles,
|
||||
// otherwise the project itself will be used
|
||||
var roleAudience []string
|
||||
if allRoles {
|
||||
roleAudience = domain.AddAudScopeToAudience(ctx, roleAudience, scopes)
|
||||
}
|
||||
|
||||
userGrants, projectRoles, err := o.assertRoles(ctx, userID, clientID, roles, roleAudience)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if projectRoles != nil && len(projectRoles.projects) > 0 {
|
||||
if roles, ok := projectRoles.projects[projectRoles.requestProjectID]; ok {
|
||||
claims = appendClaim(claims, ClaimProjectRoles, roles)
|
||||
}
|
||||
for projectID, roles := range projectRoles.projects {
|
||||
claims = appendClaim(claims, fmt.Sprintf(ClaimProjectRolesFormat, projectID), roles)
|
||||
}
|
||||
}
|
||||
|
||||
return o.privateClaimsFlows(ctx, userID, userGrants, claims)
|
||||
}
|
||||
|
||||
func (o *OPStorage) privateClaimsFlows(ctx context.Context, userID string, userGrants *query.UserGrants, claims map[string]interface{}) (map[string]interface{}, error) {
|
||||
user, err := o.query.GetUserByID(ctx, true, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queriedActions, err := o.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeCustomiseToken, domain.TriggerTypePreAccessTokenCreation, user.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctxFields := actions.SetContextFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("claims", func(c *actions.FieldConfig) interface{} {
|
||||
return c.Runtime.ToValue(claims)
|
||||
}),
|
||||
actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
return object.UserFromQuery(c, user)
|
||||
}
|
||||
}),
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} {
|
||||
return func(goja.FunctionCall) goja.Value {
|
||||
resourceOwnerQuery, err := query.NewUserMetadataResourceOwnerSearchQuery(user.ResourceOwner)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to create search query")
|
||||
panic(err)
|
||||
}
|
||||
metadata, err := o.query.SearchUserMetadata(
|
||||
ctx,
|
||||
true,
|
||||
userID,
|
||||
&query.UserMetadataSearchQueries{Queries: []query.SearchQuery{resourceOwnerQuery}},
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
logging.WithError(err).Info("unable to get md in action")
|
||||
panic(err)
|
||||
}
|
||||
return object.UserMetadataListFromQuery(c, metadata)
|
||||
}
|
||||
}),
|
||||
actions.SetFields("grants", func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserGrantsFromQuery(ctx, o.query, c, userGrants)
|
||||
}),
|
||||
),
|
||||
actions.SetFields("org",
|
||||
actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} {
|
||||
return func(goja.FunctionCall) goja.Value {
|
||||
return object.GetOrganizationMetadata(ctx, o.query, c, user.ResourceOwner)
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
for _, action := range queriedActions {
|
||||
claimLogs := []string{}
|
||||
actionCtx, cancel := context.WithTimeout(ctx, action.Timeout())
|
||||
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("claims",
|
||||
actions.SetFields("setClaim", func(key string, value interface{}) {
|
||||
if strings.HasPrefix(key, ClaimPrefix) {
|
||||
return
|
||||
}
|
||||
if _, ok := claims[key]; !ok {
|
||||
claims = appendClaim(claims, key, value)
|
||||
return
|
||||
}
|
||||
claimLogs = append(claimLogs, fmt.Sprintf("key %q already exists", key))
|
||||
}),
|
||||
actions.SetFields("appendLogIntoClaims", func(entry string) {
|
||||
claimLogs = append(claimLogs, entry)
|
||||
}),
|
||||
),
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("setMetadata", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) != 2 {
|
||||
panic("exactly 2 (key, value) arguments expected")
|
||||
}
|
||||
key := call.Arguments[0].Export().(string)
|
||||
val := call.Arguments[1].Export()
|
||||
|
||||
value, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to marshal")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
metadata := &domain.Metadata{
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
if _, err = o.command.SetUserMetadata(ctx, metadata, userID, user.ResourceOwner); err != nil {
|
||||
logging.WithError(err).Info("unable to set md in action")
|
||||
panic(err)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
err = actions.Run(
|
||||
actionCtx,
|
||||
ctxFields,
|
||||
apiFields,
|
||||
action.Script,
|
||||
action.Name,
|
||||
append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx), actions.WithUUID(actionCtx))...,
|
||||
)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(claimLogs) > 0 {
|
||||
claims = appendClaim(claims, fmt.Sprintf(ClaimActionLogFormat, action.Name), claimLogs)
|
||||
claimLogs = nil
|
||||
}
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID string, requestedRoles, roleAudience []string) (*query.UserGrants, *projectsRoles, error) {
|
||||
if (applicationID == "" || len(requestedRoles) == 0) && len(roleAudience) == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
projectID, err := o.query.ProjectIDFromClientID(ctx, applicationID)
|
||||
// applicationID might contain a username (e.g. client credentials) -> ignore the not found
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return nil, nil, err
|
||||
}
|
||||
// ensure the projectID of the requesting is part of the roleAudience
|
||||
if projectID != "" {
|
||||
roleAudience = append(roleAudience, projectID)
|
||||
}
|
||||
projectQuery, err := query.NewUserGrantProjectIDsSearchQuery(roleAudience)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
userIDQuery, err := query.NewUserGrantUserIDSearchQuery(userID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
activeQuery, err := query.NewUserGrantStateQuery(domain.UserGrantStateActive)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
grants, err := o.query.UserGrants(ctx, &query.UserGrantsQueries{
|
||||
Queries: []query.SearchQuery{
|
||||
projectQuery,
|
||||
userIDQuery,
|
||||
activeQuery,
|
||||
},
|
||||
}, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
roles := new(projectsRoles)
|
||||
// if specific roles where requested, check if they are granted and append them in the roles list
|
||||
if len(requestedRoles) > 0 {
|
||||
for _, requestedRole := range requestedRoles {
|
||||
for _, grant := range grants.UserGrants {
|
||||
checkGrantedRoles(roles, *grant, requestedRole, grant.ProjectID == projectID)
|
||||
}
|
||||
}
|
||||
return grants, roles, nil
|
||||
}
|
||||
// no specific roles were requested, so convert any grants into roles
|
||||
for _, grant := range grants.UserGrants {
|
||||
for _, role := range grant.Roles {
|
||||
roles.Add(grant.ProjectID, role, grant.ResourceOwner, grant.OrgPrimaryDomain, grant.ProjectID == projectID)
|
||||
}
|
||||
}
|
||||
return grants, roles, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertUserMetaData(ctx context.Context, userID string) (map[string]string, error) {
|
||||
metaData, err := o.query.SearchUserMetadata(ctx, true, userID, &query.UserMetadataSearchQueries{}, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMetaData := make(map[string]string)
|
||||
for _, md := range metaData.Metadata {
|
||||
userMetaData[md.Key] = base64.RawURLEncoding.EncodeToString(md.Value)
|
||||
}
|
||||
return userMetaData, nil
|
||||
}
|
||||
|
||||
func (o *OPStorage) assertUserResourceOwner(ctx context.Context, userID string) (map[string]string, error) {
|
||||
user, err := o.query.GetUserByID(ctx, true, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceOwner, err := o.query.OrgByID(ctx, true, user.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return map[string]string{
|
||||
ClaimResourceOwnerID: resourceOwner.ID,
|
||||
ClaimResourceOwnerName: resourceOwner.Name,
|
||||
ClaimResourceOwnerPrimaryDomain: resourceOwner.Domain,
|
||||
}, nil
|
||||
func (o *OPStorage) GetPrivateClaimsFromScopes(context.Context, string, string, []string) (map[string]interface{}, error) {
|
||||
panic(o.panicErr("GetPrivateClaimsFromScopes"))
|
||||
}
|
||||
|
||||
func checkGrantedRoles(roles *projectsRoles, grant query.UserGrant, requestedRole string, isRequested bool) {
|
||||
@@ -946,14 +166,6 @@ func getGender(gender domain.Gender) oidc.Gender {
|
||||
return ""
|
||||
}
|
||||
|
||||
func appendClaim(claims map[string]interface{}, claim string, value interface{}) map[string]interface{} {
|
||||
if claims == nil {
|
||||
claims = make(map[string]interface{})
|
||||
}
|
||||
claims[claim] = value
|
||||
return claims
|
||||
}
|
||||
|
||||
func userinfoClaims(userInfo *oidc.UserInfo) func(c *actions.FieldConfig) interface{} {
|
||||
return func(c *actions.FieldConfig) interface{} {
|
||||
marshalled, err := json.Marshal(userInfo)
|
||||
|
@@ -14,27 +14,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type clientCredentialsRequest struct {
|
||||
sub string
|
||||
audience []string
|
||||
scopes []string
|
||||
}
|
||||
|
||||
// GetSubject returns the subject for token to be created because of the client credentials request
|
||||
// the subject will be the id of the service user
|
||||
func (c *clientCredentialsRequest) GetSubject() string {
|
||||
return c.sub
|
||||
}
|
||||
|
||||
// GetAudience returns the audience for token to be created because of the client credentials request
|
||||
func (c *clientCredentialsRequest) GetAudience() []string {
|
||||
return c.audience
|
||||
}
|
||||
|
||||
func (c *clientCredentialsRequest) GetScopes() []string {
|
||||
return c.scopes
|
||||
}
|
||||
|
||||
func (s *Server) clientCredentialsAuth(ctx context.Context, clientID, clientSecret string) (op.Client, error) {
|
||||
user, err := s.query.GetUserByLoginName(ctx, false, clientID)
|
||||
if zerrors.IsNotFound(err) {
|
||||
|
@@ -88,6 +88,6 @@ func (o *OPStorage) StoreDeviceAuthorization(ctx context.Context, clientID, devi
|
||||
return err
|
||||
}
|
||||
|
||||
func (o *OPStorage) GetDeviceAuthorizatonState(ctx context.Context, _, deviceCode string) (state *op.DeviceAuthorizationState, err error) {
|
||||
return nil, nil
|
||||
func (o *OPStorage) GetDeviceAuthorizatonState(context.Context, string, string) (*op.DeviceAuthorizationState, error) {
|
||||
panic(o.panicErr("GetDeviceAuthorizatonState"))
|
||||
}
|
||||
|
@@ -52,13 +52,6 @@ func setTokenExchangeFeature(t *testing.T, instance *integration.Instance, value
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
func resetFeatures(t *testing.T, instance *integration.Instance) {
|
||||
iamCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
_, err := instance.Client.FeatureV2.ResetInstanceFeatures(iamCTX, &feature.ResetInstanceFeaturesRequest{})
|
||||
require.NoError(t, err)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
func setImpersonationPolicy(t *testing.T, instance *integration.Instance, value bool) {
|
||||
iamCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
|
@@ -34,22 +34,11 @@ func TestServer_UserInfo(t *testing.T) {
|
||||
})
|
||||
tests := []struct {
|
||||
name string
|
||||
legacy bool
|
||||
trigger bool
|
||||
webKey bool
|
||||
}{
|
||||
{
|
||||
name: "legacy enabled",
|
||||
legacy: true,
|
||||
},
|
||||
{
|
||||
name: "legacy disabled, trigger disabled",
|
||||
legacy: false,
|
||||
trigger: false,
|
||||
},
|
||||
{
|
||||
name: "legacy disabled, trigger enabled",
|
||||
legacy: false,
|
||||
name: "trigger enabled",
|
||||
trigger: true,
|
||||
},
|
||||
|
||||
@@ -59,7 +48,6 @@ func TestServer_UserInfo(t *testing.T) {
|
||||
// - By calling userinfo with the access token as JWT, the Token Verifier with the public key cache is tested.
|
||||
{
|
||||
name: "web keys",
|
||||
legacy: false,
|
||||
trigger: false,
|
||||
webKey: true,
|
||||
},
|
||||
@@ -68,7 +56,6 @@ func TestServer_UserInfo(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := Instance.Client.FeatureV2.SetInstanceFeatures(iamOwnerCTX, &feature.SetInstanceFeaturesRequest{
|
||||
OidcLegacyIntrospection: &tt.legacy,
|
||||
OidcTriggerIntrospectionProjections: &tt.trigger,
|
||||
WebKey: &tt.webKey,
|
||||
})
|
||||
|
@@ -25,9 +25,6 @@ func (s *Server) Introspect(ctx context.Context, r *op.Request[op.IntrospectionR
|
||||
}()
|
||||
|
||||
features := authz.GetFeatures(ctx)
|
||||
if features.LegacyIntrospection {
|
||||
return s.LegacyServer.Introspect(ctx, r)
|
||||
}
|
||||
if features.TriggerIntrospectionProjections {
|
||||
query.TriggerIntrospectionProjections(ctx)
|
||||
}
|
||||
|
@@ -3,38 +3,9 @@ package oidc
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||
"github.com/zitadel/oidc/v3/pkg/op"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func (o *OPStorage) JWTProfileTokenType(ctx context.Context, request op.TokenRequest) (_ op.AccessTokenType, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() {
|
||||
err = oidcError(err)
|
||||
span.EndWithError(err)
|
||||
}()
|
||||
|
||||
mapJWTProfileScopesToAudience(ctx, request)
|
||||
user, err := o.query.GetUserByID(ctx, false, request.GetSubject())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// the user should always be a machine, but let's just be sure
|
||||
if user.Machine == nil {
|
||||
return 0, zerrors.ThrowInvalidArgument(nil, "OIDC-jk26S", "invalid client type")
|
||||
}
|
||||
return accessTokenTypeToOIDC(user.Machine.AccessTokenType), nil
|
||||
}
|
||||
|
||||
func mapJWTProfileScopesToAudience(ctx context.Context, request op.TokenRequest) {
|
||||
// the request should always be a JWTTokenRequest, but let's make sure
|
||||
jwt, ok := request.(*oidc.JWTTokenRequest)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
jwt.Audience = domain.AddAudScopeToAudience(ctx, jwt.Audience, jwt.Scopes)
|
||||
func (o *OPStorage) JWTProfileTokenType(context.Context, op.TokenRequest) (op.AccessTokenType, error) {
|
||||
panic(o.panicErr("JWTProfileTokenType"))
|
||||
}
|
||||
|
@@ -35,9 +35,6 @@ func (s *Server) UserInfo(ctx context.Context, r *op.Request[oidc.UserInfoReques
|
||||
}()
|
||||
|
||||
features := authz.GetFeatures(ctx)
|
||||
if features.LegacyIntrospection {
|
||||
return s.LegacyServer.UserInfo(ctx, r)
|
||||
}
|
||||
if features.TriggerIntrospectionProjections {
|
||||
query.TriggerOIDCUserInfoProjections(ctx)
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@ import (
|
||||
type InstanceFeatures struct {
|
||||
LoginDefaultOrg *bool
|
||||
TriggerIntrospectionProjections *bool
|
||||
LegacyIntrospection *bool
|
||||
UserSchema *bool
|
||||
TokenExchange *bool
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
@@ -35,7 +34,6 @@ type InstanceFeatures struct {
|
||||
func (m *InstanceFeatures) isEmpty() bool {
|
||||
return m.LoginDefaultOrg == nil &&
|
||||
m.TriggerIntrospectionProjections == nil &&
|
||||
m.LegacyIntrospection == nil &&
|
||||
m.UserSchema == nil &&
|
||||
m.TokenExchange == nil &&
|
||||
// nil check to allow unset improvements
|
||||
|
@@ -68,7 +68,6 @@ func (m *InstanceFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.InstanceResetEventType,
|
||||
feature_v2.InstanceLoginDefaultOrgEventType,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType,
|
||||
feature_v2.InstanceUserSchemaEventType,
|
||||
feature_v2.InstanceTokenExchangeEventType,
|
||||
feature_v2.InstanceImprovedPerformanceEventType,
|
||||
@@ -98,9 +97,6 @@ func reduceInstanceFeature(features *InstanceFeatures, key feature.Key, value an
|
||||
case feature.KeyTriggerIntrospectionProjections:
|
||||
v := value.(bool)
|
||||
features.TriggerIntrospectionProjections = &v
|
||||
case feature.KeyLegacyIntrospection:
|
||||
v := value.(bool)
|
||||
features.LegacyIntrospection = &v
|
||||
case feature.KeyTokenExchange:
|
||||
v := value.(bool)
|
||||
features.TokenExchange = &v
|
||||
@@ -141,7 +137,6 @@ func (wm *InstanceFeaturesWriteModel) setCommands(ctx context.Context, f *Instan
|
||||
cmds := make([]eventstore.Command, 0, len(feature.KeyValues())-1)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LoginDefaultOrg, f.LoginDefaultOrg, feature_v2.InstanceLoginDefaultOrgEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.TriggerIntrospectionProjections, f.TriggerIntrospectionProjections, feature_v2.InstanceTriggerIntrospectionProjectionsEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LegacyIntrospection, f.LegacyIntrospection, feature_v2.InstanceLegacyIntrospectionEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.TokenExchange, f.TokenExchange, feature_v2.InstanceTokenExchangeEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.UserSchema, f.UserSchema, feature_v2.InstanceUserSchemaEventType)
|
||||
cmds = appendFeatureSliceUpdate(ctx, cmds, aggregate, wm.ImprovedPerformance, f.ImprovedPerformance, feature_v2.InstanceImprovedPerformanceEventType)
|
||||
|
@@ -113,24 +113,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set LegacyIntrospection",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
feature_v2.NewSetEvent[bool](
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, true,
|
||||
),
|
||||
),
|
||||
),
|
||||
args: args{ctx, &InstanceFeatures{
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
}},
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "instance1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set UserSchema",
|
||||
eventstore: expectEventstore(
|
||||
@@ -156,12 +138,12 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
expectPushFailed(io.ErrClosedPipe,
|
||||
feature_v2.NewSetEvent[bool](
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, true,
|
||||
feature_v2.InstanceConsoleUseV2UserApi, true,
|
||||
),
|
||||
),
|
||||
),
|
||||
args: args{ctx, &InstanceFeatures{
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
ConsoleUseV2UserApi: gu.Ptr(true),
|
||||
}},
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
@@ -178,10 +160,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType, false,
|
||||
),
|
||||
feature_v2.NewSetEvent[bool](
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, true,
|
||||
),
|
||||
feature_v2.NewSetEvent[bool](
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceUserSchemaEventType, true,
|
||||
@@ -195,7 +173,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
args: args{ctx, &InstanceFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(true),
|
||||
}},
|
||||
@@ -224,10 +201,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLoginDefaultOrgEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent[bool](
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, true,
|
||||
)),
|
||||
feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.InstanceOIDCSingleV1SessionTerminationEventType, false,
|
||||
@@ -247,7 +220,6 @@ func TestCommands_SetInstanceFeatures(t *testing.T) {
|
||||
args: args{ctx, &InstanceFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(false),
|
||||
}},
|
||||
want: &domain.ObjectDetails{
|
||||
|
@@ -226,37 +226,6 @@ func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, ap
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *Commands) VerifyAPIClientSecret(ctx context.Context, projectID, appID, secret string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
app, err := c.getAPIAppWriteModel(ctx, projectID, appID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !app.State.Exists() {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-DFnbf", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
if !app.IsAPI() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-Bf3fw", "Errors.Project.App.IsNotAPI")
|
||||
}
|
||||
if app.HashedSecret == "" {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D3t5g", "Errors.Project.App.APIConfigInvalid")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&app.WriteModel)
|
||||
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "passwap.Verify")
|
||||
updated, err := c.secretHasher.Verify(app.HashedSecret, secret)
|
||||
spanPasswordComparison.EndWithError(err)
|
||||
if err != nil {
|
||||
return zerrors.ThrowInvalidArgument(err, "COMMAND-SADfg", "Errors.Project.App.ClientSecretInvalid")
|
||||
}
|
||||
if updated != "" {
|
||||
c.apiUpdateSecret(ctx, projectAgg, app.AppID, updated)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) APIUpdateSecret(ctx context.Context, appID, projectID, resourceOwner, updated string) {
|
||||
agg := project_repo.NewAggregate(projectID, resourceOwner)
|
||||
c.apiUpdateSecret(ctx, &agg.Aggregate, appID, updated)
|
||||
|
@@ -2,16 +2,11 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zitadel/passwap"
|
||||
"github.com/zitadel/passwap/bcrypt"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
@@ -771,99 +766,3 @@ func newAPIAppChangedEvent(ctx context.Context, appID, projectID, resourceOwner
|
||||
)
|
||||
return event
|
||||
}
|
||||
|
||||
func TestCommands_VerifyAPIClientSecret(t *testing.T) {
|
||||
hasher := &crypto.Hasher{
|
||||
Swapper: passwap.NewSwapper(bcrypt.New(bcrypt.MinCost)),
|
||||
}
|
||||
hashedSecret, err := hasher.Hash("secret")
|
||||
require.NoError(t, err)
|
||||
agg := project.NewAggregate("projectID", "orgID")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secret string
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "filter error",
|
||||
eventstore: expectEventstore(
|
||||
expectFilterError(io.ErrClosedPipe),
|
||||
),
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
{
|
||||
name: "app not exists",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
),
|
||||
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-DFnbf", "Errors.Project.App.NotExisting"),
|
||||
},
|
||||
{
|
||||
name: "wrong app type",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-Bf3fw", "Errors.Project.App.IsNotAPI"),
|
||||
},
|
||||
{
|
||||
name: "no secret set",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", "", domain.APIAuthMethodTypePrivateKeyJWT),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D3t5g", "Errors.Project.App.APIConfigInvalid"),
|
||||
},
|
||||
{
|
||||
name: "check succeeded",
|
||||
secret: "secret",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", hashedSecret, domain.APIAuthMethodTypePrivateKeyJWT),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "check failed",
|
||||
secret: "wrong!",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", hashedSecret, domain.APIAuthMethodTypePrivateKeyJWT),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowInvalidArgument(err, "COMMAND-SADfg", "Errors.Project.App.ClientSecretInvalid"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.eventstore(t),
|
||||
secretHasher: hasher,
|
||||
}
|
||||
err := c.VerifyAPIClientSecret(context.Background(), "projectID", "appID", tt.secret)
|
||||
c.jobs.Wait()
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -322,37 +322,6 @@ func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, a
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *Commands) VerifyOIDCClientSecret(ctx context.Context, projectID, appID, secret string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
app, err := c.getOIDCAppWriteModel(ctx, projectID, appID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !app.State.Exists() {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D8hba", "Errors.Project.App.NotExisting")
|
||||
}
|
||||
if !app.IsOIDC() {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-BHgn2", "Errors.Project.App.IsNotOIDC")
|
||||
}
|
||||
if app.HashedSecret == "" {
|
||||
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.OIDCConfigInvalid")
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&app.WriteModel)
|
||||
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "passwap.Verify")
|
||||
updated, err := c.secretHasher.Verify(app.HashedSecret, secret)
|
||||
spanPasswordComparison.EndWithError(err)
|
||||
if err != nil {
|
||||
return zerrors.ThrowInvalidArgument(err, "COMMAND-Bz542", "Errors.Project.App.ClientSecretInvalid")
|
||||
}
|
||||
if updated != "" {
|
||||
c.oidcUpdateSecret(ctx, projectAgg, appID, updated)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) OIDCUpdateSecret(ctx context.Context, appID, projectID, resourceOwner, updated string) {
|
||||
agg := project_repo.NewAggregate(projectID, resourceOwner)
|
||||
c.oidcUpdateSecret(ctx, &agg.Aggregate, appID, updated)
|
||||
|
@@ -2,18 +2,13 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zitadel/passwap"
|
||||
"github.com/zitadel/passwap/bcrypt"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
@@ -1307,168 +1302,3 @@ func newOIDCAppChangedEvent(ctx context.Context, appID, projectID, resourceOwner
|
||||
)
|
||||
return event
|
||||
}
|
||||
|
||||
func TestCommands_VerifyOIDCClientSecret(t *testing.T) {
|
||||
hasher := &crypto.Hasher{
|
||||
Swapper: passwap.NewSwapper(bcrypt.New(bcrypt.MinCost)),
|
||||
}
|
||||
hashedSecret, err := hasher.Hash("secret")
|
||||
require.NoError(t, err)
|
||||
agg := project.NewAggregate("projectID", "orgID")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
secret string
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "filter error",
|
||||
eventstore: expectEventstore(
|
||||
expectFilterError(io.ErrClosedPipe),
|
||||
),
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
{
|
||||
name: "app not exists",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
),
|
||||
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D8hba", "Errors.Project.App.NotExisting"),
|
||||
},
|
||||
{
|
||||
name: "wrong app type",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-BHgn2", "Errors.Project.App.IsNotOIDC"),
|
||||
},
|
||||
{
|
||||
name: "no secret set",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewOIDCConfigAddedEvent(context.Background(),
|
||||
&agg.Aggregate,
|
||||
domain.OIDCVersionV1,
|
||||
"appID",
|
||||
"client1@project",
|
||||
"",
|
||||
[]string{"https://test.ch"},
|
||||
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
|
||||
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
|
||||
domain.OIDCApplicationTypeWeb,
|
||||
domain.OIDCAuthMethodTypePost,
|
||||
[]string{"https://test.ch/logout"},
|
||||
true,
|
||||
domain.OIDCTokenTypeBearer,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"},
|
||||
false,
|
||||
"",
|
||||
domain.LoginVersionUnspecified,
|
||||
"",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.OIDCConfigInvalid"),
|
||||
},
|
||||
{
|
||||
name: "check succeeded",
|
||||
secret: "secret",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewOIDCConfigAddedEvent(context.Background(),
|
||||
&agg.Aggregate,
|
||||
domain.OIDCVersionV1,
|
||||
"appID",
|
||||
"client1@project",
|
||||
hashedSecret,
|
||||
[]string{"https://test.ch"},
|
||||
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
|
||||
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
|
||||
domain.OIDCApplicationTypeWeb,
|
||||
domain.OIDCAuthMethodTypePost,
|
||||
[]string{"https://test.ch/logout"},
|
||||
true,
|
||||
domain.OIDCTokenTypeBearer,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"},
|
||||
false,
|
||||
"",
|
||||
domain.LoginVersionUnspecified,
|
||||
"",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "check failed",
|
||||
secret: "wrong!",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
project.NewOIDCConfigAddedEvent(context.Background(),
|
||||
&agg.Aggregate,
|
||||
domain.OIDCVersionV1,
|
||||
"appID",
|
||||
"client1@project",
|
||||
hashedSecret,
|
||||
[]string{"https://test.ch"},
|
||||
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
|
||||
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
|
||||
domain.OIDCApplicationTypeWeb,
|
||||
domain.OIDCAuthMethodTypePost,
|
||||
[]string{"https://test.ch/logout"},
|
||||
true,
|
||||
domain.OIDCTokenTypeBearer,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
time.Second*1,
|
||||
[]string{"https://sub.test.ch"},
|
||||
false,
|
||||
"",
|
||||
domain.LoginVersionUnspecified,
|
||||
"",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
wantErr: zerrors.ThrowInvalidArgument(err, "COMMAND-Bz542", "Errors.Project.App.ClientSecretInvalid"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.eventstore(t),
|
||||
secretHasher: hasher,
|
||||
}
|
||||
err := c.VerifyOIDCClientSecret(context.Background(), "projectID", "appID", tt.secret)
|
||||
c.jobs.Wait()
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@ import (
|
||||
type SystemFeatures struct {
|
||||
LoginDefaultOrg *bool
|
||||
TriggerIntrospectionProjections *bool
|
||||
LegacyIntrospection *bool
|
||||
TokenExchange *bool
|
||||
UserSchema *bool
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
@@ -26,7 +25,6 @@ type SystemFeatures struct {
|
||||
func (m *SystemFeatures) isEmpty() bool {
|
||||
return m.LoginDefaultOrg == nil &&
|
||||
m.TriggerIntrospectionProjections == nil &&
|
||||
m.LegacyIntrospection == nil &&
|
||||
m.UserSchema == nil &&
|
||||
m.TokenExchange == nil &&
|
||||
// nil check to allow unset improvements
|
||||
|
@@ -61,7 +61,6 @@ func (m *SystemFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.SystemResetEventType,
|
||||
feature_v2.SystemLoginDefaultOrgEventType,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType,
|
||||
feature_v2.SystemLegacyIntrospectionEventType,
|
||||
feature_v2.SystemUserSchemaEventType,
|
||||
feature_v2.SystemTokenExchangeEventType,
|
||||
feature_v2.SystemImprovedPerformanceEventType,
|
||||
@@ -88,9 +87,6 @@ func reduceSystemFeature(features *SystemFeatures, key feature.Key, value any) {
|
||||
case feature.KeyTriggerIntrospectionProjections:
|
||||
v := value.(bool)
|
||||
features.TriggerIntrospectionProjections = &v
|
||||
case feature.KeyLegacyIntrospection:
|
||||
v := value.(bool)
|
||||
features.LegacyIntrospection = &v
|
||||
case feature.KeyUserSchema:
|
||||
v := value.(bool)
|
||||
features.UserSchema = &v
|
||||
@@ -121,7 +117,6 @@ func (wm *SystemFeaturesWriteModel) setCommands(ctx context.Context, f *SystemFe
|
||||
cmds := make([]eventstore.Command, 0, len(feature.KeyValues())-1)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LoginDefaultOrg, f.LoginDefaultOrg, feature_v2.SystemLoginDefaultOrgEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.TriggerIntrospectionProjections, f.TriggerIntrospectionProjections, feature_v2.SystemTriggerIntrospectionProjectionsEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LegacyIntrospection, f.LegacyIntrospection, feature_v2.SystemLegacyIntrospectionEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.UserSchema, f.UserSchema, feature_v2.SystemUserSchemaEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.TokenExchange, f.TokenExchange, feature_v2.SystemTokenExchangeEventType)
|
||||
cmds = appendFeatureSliceUpdate(ctx, cmds, aggregate, wm.ImprovedPerformance, f.ImprovedPerformance, feature_v2.SystemImprovedPerformanceEventType)
|
||||
|
@@ -81,24 +81,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
ResourceOwner: "SYSTEM",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set LegacyIntrospection",
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, true,
|
||||
),
|
||||
),
|
||||
),
|
||||
args: args{context.Background(), &SystemFeatures{
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
}},
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "SYSTEM",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set UserSchema",
|
||||
eventstore: expectEventstore(
|
||||
@@ -124,12 +106,12 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
expectPushFailed(io.ErrClosedPipe,
|
||||
feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, true,
|
||||
feature_v2.SystemEnableBackChannelLogout, true,
|
||||
),
|
||||
),
|
||||
),
|
||||
args: args{context.Background(), &SystemFeatures{
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
}},
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
@@ -146,10 +128,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType, false,
|
||||
),
|
||||
feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, true,
|
||||
),
|
||||
feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemUserSchemaEventType, true,
|
||||
@@ -163,7 +141,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
args: args{context.Background(), &SystemFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(true),
|
||||
}},
|
||||
@@ -192,10 +169,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLoginDefaultOrgEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent[bool](
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, true,
|
||||
)),
|
||||
),
|
||||
expectPush(
|
||||
feature_v2.NewSetEvent[bool](
|
||||
@@ -219,7 +192,6 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
args: args{context.Background(), &SystemFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
TriggerIntrospectionProjections: gu.Ptr(false),
|
||||
LegacyIntrospection: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(false),
|
||||
}},
|
||||
|
@@ -9,22 +9,22 @@ import (
|
||||
type Key int
|
||||
|
||||
const (
|
||||
KeyUnspecified Key = iota
|
||||
KeyLoginDefaultOrg
|
||||
KeyTriggerIntrospectionProjections
|
||||
KeyLegacyIntrospection
|
||||
KeyUserSchema
|
||||
KeyTokenExchange
|
||||
KeyActionsDeprecated
|
||||
KeyImprovedPerformance
|
||||
KeyWebKey
|
||||
KeyDebugOIDCParentError
|
||||
KeyOIDCSingleV1SessionTermination
|
||||
KeyDisableUserTokenEvent
|
||||
KeyEnableBackChannelLogout
|
||||
KeyLoginV2
|
||||
KeyPermissionCheckV2
|
||||
KeyConsoleUseV2UserApi
|
||||
// Reserved: 3, 6
|
||||
|
||||
KeyUnspecified Key = 0
|
||||
KeyLoginDefaultOrg Key = 1
|
||||
KeyTriggerIntrospectionProjections Key = 2
|
||||
KeyUserSchema Key = 4
|
||||
KeyTokenExchange Key = 5
|
||||
KeyImprovedPerformance Key = 7
|
||||
KeyWebKey Key = 8
|
||||
KeyDebugOIDCParentError Key = 9
|
||||
KeyOIDCSingleV1SessionTermination Key = 10
|
||||
KeyDisableUserTokenEvent Key = 11
|
||||
KeyEnableBackChannelLogout Key = 12
|
||||
KeyLoginV2 Key = 13
|
||||
KeyPermissionCheckV2 Key = 14
|
||||
KeyConsoleUseV2UserApi Key = 15
|
||||
)
|
||||
|
||||
//go:generate enumer -type Level -transform snake -trimprefix Level
|
||||
@@ -43,7 +43,6 @@ const (
|
||||
type Features struct {
|
||||
LoginDefaultOrg bool `json:"login_default_org,omitempty"`
|
||||
TriggerIntrospectionProjections bool `json:"trigger_introspection_projections,omitempty"`
|
||||
LegacyIntrospection bool `json:"legacy_introspection,omitempty"`
|
||||
UserSchema bool `json:"user_schema,omitempty"`
|
||||
TokenExchange bool `json:"token_exchange,omitempty"`
|
||||
ImprovedPerformance []ImprovedPerformanceType `json:"improved_performance,omitempty"`
|
||||
|
@@ -12,7 +12,6 @@ func TestKey(t *testing.T) {
|
||||
"unspecified",
|
||||
"login_default_org",
|
||||
"trigger_introspection_projections",
|
||||
"legacy_introspection",
|
||||
}
|
||||
for _, want := range tests {
|
||||
t.Run(want, func(t *testing.T) {
|
||||
|
@@ -7,17 +7,34 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _KeyName = "unspecifiedlogin_default_orgtrigger_introspection_projectionslegacy_introspectionuser_schematoken_exchangeactions_deprecatedimproved_performanceweb_keydebug_oidc_parent_erroroidc_single_v1_session_terminationdisable_user_token_eventenable_back_channel_logoutlogin_v2permission_check_v2console_use_v2_user_api"
|
||||
const (
|
||||
_KeyName_0 = "unspecifiedlogin_default_orgtrigger_introspection_projections"
|
||||
_KeyLowerName_0 = "unspecifiedlogin_default_orgtrigger_introspection_projections"
|
||||
_KeyName_1 = "user_schematoken_exchange"
|
||||
_KeyLowerName_1 = "user_schematoken_exchange"
|
||||
_KeyName_2 = "improved_performanceweb_keydebug_oidc_parent_erroroidc_single_v1_session_terminationdisable_user_token_eventenable_back_channel_logoutlogin_v2permission_check_v2console_use_v2_user_api"
|
||||
_KeyLowerName_2 = "improved_performanceweb_keydebug_oidc_parent_erroroidc_single_v1_session_terminationdisable_user_token_eventenable_back_channel_logoutlogin_v2permission_check_v2console_use_v2_user_api"
|
||||
)
|
||||
|
||||
var _KeyIndex = [...]uint16{0, 11, 28, 61, 81, 92, 106, 124, 144, 151, 174, 208, 232, 258, 266, 285, 308}
|
||||
|
||||
const _KeyLowerName = "unspecifiedlogin_default_orgtrigger_introspection_projectionslegacy_introspectionuser_schematoken_exchangeactions_deprecatedimproved_performanceweb_keydebug_oidc_parent_erroroidc_single_v1_session_terminationdisable_user_token_eventenable_back_channel_logoutlogin_v2permission_check_v2console_use_v2_user_api"
|
||||
var (
|
||||
_KeyIndex_0 = [...]uint8{0, 11, 28, 61}
|
||||
_KeyIndex_1 = [...]uint8{0, 11, 25}
|
||||
_KeyIndex_2 = [...]uint8{0, 20, 27, 50, 84, 108, 134, 142, 161, 184}
|
||||
)
|
||||
|
||||
func (i Key) String() string {
|
||||
if i < 0 || i >= Key(len(_KeyIndex)-1) {
|
||||
switch {
|
||||
case 0 <= i && i <= 2:
|
||||
return _KeyName_0[_KeyIndex_0[i]:_KeyIndex_0[i+1]]
|
||||
case 4 <= i && i <= 5:
|
||||
i -= 4
|
||||
return _KeyName_1[_KeyIndex_1[i]:_KeyIndex_1[i+1]]
|
||||
case 7 <= i && i <= 15:
|
||||
i -= 7
|
||||
return _KeyName_2[_KeyIndex_2[i]:_KeyIndex_2[i+1]]
|
||||
default:
|
||||
return fmt.Sprintf("Key(%d)", i)
|
||||
}
|
||||
return _KeyName[_KeyIndex[i]:_KeyIndex[i+1]]
|
||||
}
|
||||
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
@@ -27,10 +44,8 @@ func _KeyNoOp() {
|
||||
_ = x[KeyUnspecified-(0)]
|
||||
_ = x[KeyLoginDefaultOrg-(1)]
|
||||
_ = x[KeyTriggerIntrospectionProjections-(2)]
|
||||
_ = x[KeyLegacyIntrospection-(3)]
|
||||
_ = x[KeyUserSchema-(4)]
|
||||
_ = x[KeyTokenExchange-(5)]
|
||||
_ = x[KeyActionsDeprecated-(6)]
|
||||
_ = x[KeyImprovedPerformance-(7)]
|
||||
_ = x[KeyWebKey-(8)]
|
||||
_ = x[KeyDebugOIDCParentError-(9)]
|
||||
@@ -42,60 +57,54 @@ func _KeyNoOp() {
|
||||
_ = x[KeyConsoleUseV2UserApi-(15)]
|
||||
}
|
||||
|
||||
var _KeyValues = []Key{KeyUnspecified, KeyLoginDefaultOrg, KeyTriggerIntrospectionProjections, KeyLegacyIntrospection, KeyUserSchema, KeyTokenExchange, KeyActionsDeprecated, KeyImprovedPerformance, KeyWebKey, KeyDebugOIDCParentError, KeyOIDCSingleV1SessionTermination, KeyDisableUserTokenEvent, KeyEnableBackChannelLogout, KeyLoginV2, KeyPermissionCheckV2, KeyConsoleUseV2UserApi}
|
||||
var _KeyValues = []Key{KeyUnspecified, KeyLoginDefaultOrg, KeyTriggerIntrospectionProjections, KeyUserSchema, KeyTokenExchange, KeyImprovedPerformance, KeyWebKey, KeyDebugOIDCParentError, KeyOIDCSingleV1SessionTermination, KeyDisableUserTokenEvent, KeyEnableBackChannelLogout, KeyLoginV2, KeyPermissionCheckV2, KeyConsoleUseV2UserApi}
|
||||
|
||||
var _KeyNameToValueMap = map[string]Key{
|
||||
_KeyName[0:11]: KeyUnspecified,
|
||||
_KeyLowerName[0:11]: KeyUnspecified,
|
||||
_KeyName[11:28]: KeyLoginDefaultOrg,
|
||||
_KeyLowerName[11:28]: KeyLoginDefaultOrg,
|
||||
_KeyName[28:61]: KeyTriggerIntrospectionProjections,
|
||||
_KeyLowerName[28:61]: KeyTriggerIntrospectionProjections,
|
||||
_KeyName[61:81]: KeyLegacyIntrospection,
|
||||
_KeyLowerName[61:81]: KeyLegacyIntrospection,
|
||||
_KeyName[81:92]: KeyUserSchema,
|
||||
_KeyLowerName[81:92]: KeyUserSchema,
|
||||
_KeyName[92:106]: KeyTokenExchange,
|
||||
_KeyLowerName[92:106]: KeyTokenExchange,
|
||||
_KeyName[106:124]: KeyActionsDeprecated,
|
||||
_KeyLowerName[106:124]: KeyActionsDeprecated,
|
||||
_KeyName[124:144]: KeyImprovedPerformance,
|
||||
_KeyLowerName[124:144]: KeyImprovedPerformance,
|
||||
_KeyName[144:151]: KeyWebKey,
|
||||
_KeyLowerName[144:151]: KeyWebKey,
|
||||
_KeyName[151:174]: KeyDebugOIDCParentError,
|
||||
_KeyLowerName[151:174]: KeyDebugOIDCParentError,
|
||||
_KeyName[174:208]: KeyOIDCSingleV1SessionTermination,
|
||||
_KeyLowerName[174:208]: KeyOIDCSingleV1SessionTermination,
|
||||
_KeyName[208:232]: KeyDisableUserTokenEvent,
|
||||
_KeyLowerName[208:232]: KeyDisableUserTokenEvent,
|
||||
_KeyName[232:258]: KeyEnableBackChannelLogout,
|
||||
_KeyLowerName[232:258]: KeyEnableBackChannelLogout,
|
||||
_KeyName[258:266]: KeyLoginV2,
|
||||
_KeyLowerName[258:266]: KeyLoginV2,
|
||||
_KeyName[266:285]: KeyPermissionCheckV2,
|
||||
_KeyLowerName[266:285]: KeyPermissionCheckV2,
|
||||
_KeyName[285:308]: KeyConsoleUseV2UserApi,
|
||||
_KeyLowerName[285:308]: KeyConsoleUseV2UserApi,
|
||||
_KeyName_0[0:11]: KeyUnspecified,
|
||||
_KeyLowerName_0[0:11]: KeyUnspecified,
|
||||
_KeyName_0[11:28]: KeyLoginDefaultOrg,
|
||||
_KeyLowerName_0[11:28]: KeyLoginDefaultOrg,
|
||||
_KeyName_0[28:61]: KeyTriggerIntrospectionProjections,
|
||||
_KeyLowerName_0[28:61]: KeyTriggerIntrospectionProjections,
|
||||
_KeyName_1[0:11]: KeyUserSchema,
|
||||
_KeyLowerName_1[0:11]: KeyUserSchema,
|
||||
_KeyName_1[11:25]: KeyTokenExchange,
|
||||
_KeyLowerName_1[11:25]: KeyTokenExchange,
|
||||
_KeyName_2[0:20]: KeyImprovedPerformance,
|
||||
_KeyLowerName_2[0:20]: KeyImprovedPerformance,
|
||||
_KeyName_2[20:27]: KeyWebKey,
|
||||
_KeyLowerName_2[20:27]: KeyWebKey,
|
||||
_KeyName_2[27:50]: KeyDebugOIDCParentError,
|
||||
_KeyLowerName_2[27:50]: KeyDebugOIDCParentError,
|
||||
_KeyName_2[50:84]: KeyOIDCSingleV1SessionTermination,
|
||||
_KeyLowerName_2[50:84]: KeyOIDCSingleV1SessionTermination,
|
||||
_KeyName_2[84:108]: KeyDisableUserTokenEvent,
|
||||
_KeyLowerName_2[84:108]: KeyDisableUserTokenEvent,
|
||||
_KeyName_2[108:134]: KeyEnableBackChannelLogout,
|
||||
_KeyLowerName_2[108:134]: KeyEnableBackChannelLogout,
|
||||
_KeyName_2[134:142]: KeyLoginV2,
|
||||
_KeyLowerName_2[134:142]: KeyLoginV2,
|
||||
_KeyName_2[142:161]: KeyPermissionCheckV2,
|
||||
_KeyLowerName_2[142:161]: KeyPermissionCheckV2,
|
||||
_KeyName_2[161:184]: KeyConsoleUseV2UserApi,
|
||||
_KeyLowerName_2[161:184]: KeyConsoleUseV2UserApi,
|
||||
}
|
||||
|
||||
var _KeyNames = []string{
|
||||
_KeyName[0:11],
|
||||
_KeyName[11:28],
|
||||
_KeyName[28:61],
|
||||
_KeyName[61:81],
|
||||
_KeyName[81:92],
|
||||
_KeyName[92:106],
|
||||
_KeyName[106:124],
|
||||
_KeyName[124:144],
|
||||
_KeyName[144:151],
|
||||
_KeyName[151:174],
|
||||
_KeyName[174:208],
|
||||
_KeyName[208:232],
|
||||
_KeyName[232:258],
|
||||
_KeyName[258:266],
|
||||
_KeyName[266:285],
|
||||
_KeyName[285:308],
|
||||
_KeyName_0[0:11],
|
||||
_KeyName_0[11:28],
|
||||
_KeyName_0[28:61],
|
||||
_KeyName_1[0:11],
|
||||
_KeyName_1[11:25],
|
||||
_KeyName_2[0:20],
|
||||
_KeyName_2[20:27],
|
||||
_KeyName_2[27:50],
|
||||
_KeyName_2[50:84],
|
||||
_KeyName_2[84:108],
|
||||
_KeyName_2[108:134],
|
||||
_KeyName_2[134:142],
|
||||
_KeyName_2[142:161],
|
||||
_KeyName_2[161:184],
|
||||
}
|
||||
|
||||
// KeyString retrieves an enum value from the enum constants string name.
|
||||
|
@@ -455,27 +455,6 @@ func (q *Queries) ProjectIDFromClientID(ctx context.Context, appID string) (id s
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (q *Queries) ProjectByOIDCClientID(ctx context.Context, id string) (project *Project, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareProjectByOIDCAppQuery()
|
||||
eq := sq.Eq{
|
||||
AppOIDCConfigColumnClientID.identifier(): id,
|
||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
}
|
||||
query, args, err := stmt.Where(eq).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-XhJi4", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
err = q.client.QueryRowContext(ctx, func(row *sql.Row) error {
|
||||
project, err = scan(row)
|
||||
return err
|
||||
}, query, args...)
|
||||
return project, err
|
||||
}
|
||||
|
||||
func (q *Queries) AppByOIDCClientID(ctx context.Context, clientID string) (app *App, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
@@ -497,35 +476,6 @@ func (q *Queries) AppByOIDCClientID(ctx context.Context, clientID string) (app *
|
||||
return app, err
|
||||
}
|
||||
|
||||
func (q *Queries) AppByClientID(ctx context.Context, clientID string) (app *App, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareAppQuery(true)
|
||||
eq := sq.Eq{
|
||||
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
AppColumnState.identifier(): domain.AppStateActive,
|
||||
ProjectColumnState.identifier(): domain.ProjectStateActive,
|
||||
OrgColumnState.identifier(): domain.OrgStateActive,
|
||||
}
|
||||
query, args, err := stmt.Where(sq.And{
|
||||
eq,
|
||||
sq.Or{
|
||||
sq.Eq{AppOIDCConfigColumnClientID.identifier(): clientID},
|
||||
sq.Eq{AppAPIConfigColumnClientID.identifier(): clientID},
|
||||
},
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-Dfge2", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
err = q.client.QueryRowContext(ctx, func(row *sql.Row) error {
|
||||
app, err = scan(row)
|
||||
return err
|
||||
}, query, args...)
|
||||
return app, err
|
||||
}
|
||||
|
||||
func (q *Queries) SearchApps(ctx context.Context, queries *AppSearchQueries, withOwnerRemoved bool) (apps *Apps, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
@@ -867,48 +817,6 @@ func prepareProjectIDByAppQuery() (sq.SelectBuilder, func(*sql.Row) (projectID s
|
||||
}
|
||||
}
|
||||
|
||||
func prepareProjectByOIDCAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
|
||||
return sq.Select(
|
||||
ProjectColumnID.identifier(),
|
||||
ProjectColumnCreationDate.identifier(),
|
||||
ProjectColumnChangeDate.identifier(),
|
||||
ProjectColumnResourceOwner.identifier(),
|
||||
ProjectColumnState.identifier(),
|
||||
ProjectColumnSequence.identifier(),
|
||||
ProjectColumnName.identifier(),
|
||||
ProjectColumnProjectRoleAssertion.identifier(),
|
||||
ProjectColumnProjectRoleCheck.identifier(),
|
||||
ProjectColumnHasProjectCheck.identifier(),
|
||||
ProjectColumnPrivateLabelingSetting.identifier(),
|
||||
).From(projectsTable.identifier()).
|
||||
Join(join(AppColumnProjectID, ProjectColumnID)).
|
||||
Join(join(AppOIDCConfigColumnAppID, AppColumnID)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*Project, error) {
|
||||
p := new(Project)
|
||||
err := row.Scan(
|
||||
&p.ID,
|
||||
&p.CreationDate,
|
||||
&p.ChangeDate,
|
||||
&p.ResourceOwner,
|
||||
&p.State,
|
||||
&p.Sequence,
|
||||
&p.Name,
|
||||
&p.ProjectRoleAssertion,
|
||||
&p.ProjectRoleCheck,
|
||||
&p.HasProjectCheck,
|
||||
&p.PrivateLabelingSetting,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, zerrors.ThrowNotFound(err, "QUERY-yxTMh", "Errors.Project.NotFound")
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-dj2FF", "Errors.Internal")
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
|
||||
return sq.Select(
|
||||
ProjectColumnID.identifier(),
|
||||
|
@@ -254,34 +254,6 @@ func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, i
|
||||
return key, err
|
||||
}
|
||||
|
||||
func (q *Queries) GetAuthNKeyPublicKeyByIDAndIdentifier(ctx context.Context, id string, identifier string) (key []byte, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
stmt, scan := prepareAuthNKeyPublicKeyQuery()
|
||||
eq := sq.And{
|
||||
sq.Eq{
|
||||
AuthNKeyColumnID.identifier(): id,
|
||||
AuthNKeyColumnIdentifier.identifier(): identifier,
|
||||
AuthNKeyColumnEnabled.identifier(): true,
|
||||
AuthNKeyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
},
|
||||
sq.Gt{
|
||||
AuthNKeyColumnExpiration.identifier(): time.Now(),
|
||||
},
|
||||
}
|
||||
query, args, err := stmt.Where(eq).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-DAb32", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
err = q.client.QueryRowContext(ctx, func(row *sql.Row) error {
|
||||
key, err = scan(row)
|
||||
return err
|
||||
}, query, args...)
|
||||
return key, err
|
||||
}
|
||||
|
||||
func NewAuthNKeyResourceOwnerQuery(id string) (SearchQuery, error) {
|
||||
return NewTextQuery(AuthNKeyColumnResourceOwner, id, TextEquals)
|
||||
}
|
||||
@@ -429,26 +401,6 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er
|
||||
}
|
||||
}
|
||||
|
||||
func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]byte, error)) {
|
||||
return sq.Select(
|
||||
AuthNKeyColumnPublicKey.identifier(),
|
||||
).From(authNKeyTable.identifier()).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) ([]byte, error) {
|
||||
var publicKey []byte
|
||||
err := row.Scan(
|
||||
&publicKey,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, zerrors.ThrowNotFound(err, "QUERY-SDf32", "Errors.AuthNKey.NotFound")
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-Bfs2a", "Errors.Internal")
|
||||
}
|
||||
return publicKey, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
|
||||
return sq.Select(
|
||||
AuthNKeyColumnID.identifier(),
|
||||
|
@@ -423,55 +423,6 @@ func Test_AuthNKeyPrepares(t *testing.T) {
|
||||
},
|
||||
object: (*AuthNKey)(nil),
|
||||
},
|
||||
{
|
||||
name: "prepareAuthNKeyPublicKeyQuery no result",
|
||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueriesScanErr(
|
||||
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !zerrors.IsNotFound(err) {
|
||||
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: ([]byte)(nil),
|
||||
},
|
||||
{
|
||||
name: "prepareAuthNKeyPublicKeyQuery found",
|
||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||
prepareAuthNKeyPublicKeyCols,
|
||||
[]driver.Value{
|
||||
[]byte("publicKey"),
|
||||
},
|
||||
),
|
||||
},
|
||||
object: []byte("publicKey"),
|
||||
},
|
||||
{
|
||||
name: "prepareAuthNKeyPublicKeyQuery sql err",
|
||||
prepare: prepareAuthNKeyPublicKeyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !errors.Is(err, sql.ErrConnDone) {
|
||||
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: ([]byte)(nil),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@@ -11,7 +11,6 @@ type InstanceFeatures struct {
|
||||
Details *domain.ObjectDetails
|
||||
LoginDefaultOrg FeatureSource[bool]
|
||||
TriggerIntrospectionProjections FeatureSource[bool]
|
||||
LegacyIntrospection FeatureSource[bool]
|
||||
UserSchema FeatureSource[bool]
|
||||
TokenExchange FeatureSource[bool]
|
||||
ImprovedPerformance FeatureSource[[]feature.ImprovedPerformanceType]
|
||||
|
@@ -64,7 +64,6 @@ func (m *InstanceFeaturesReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.InstanceResetEventType,
|
||||
feature_v2.InstanceLoginDefaultOrgEventType,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType,
|
||||
feature_v2.InstanceUserSchemaEventType,
|
||||
feature_v2.InstanceTokenExchangeEventType,
|
||||
feature_v2.InstanceImprovedPerformanceEventType,
|
||||
@@ -94,7 +93,6 @@ func (m *InstanceFeaturesReadModel) populateFromSystem() bool {
|
||||
}
|
||||
m.instance.LoginDefaultOrg = m.system.LoginDefaultOrg
|
||||
m.instance.TriggerIntrospectionProjections = m.system.TriggerIntrospectionProjections
|
||||
m.instance.LegacyIntrospection = m.system.LegacyIntrospection
|
||||
m.instance.UserSchema = m.system.UserSchema
|
||||
m.instance.TokenExchange = m.system.TokenExchange
|
||||
m.instance.ImprovedPerformance = m.system.ImprovedPerformance
|
||||
@@ -111,15 +109,12 @@ func reduceInstanceFeatureSet[T any](features *InstanceFeatures, event *feature_
|
||||
return err
|
||||
}
|
||||
switch key {
|
||||
case feature.KeyUnspecified,
|
||||
feature.KeyActionsDeprecated:
|
||||
case feature.KeyUnspecified:
|
||||
return nil
|
||||
case feature.KeyLoginDefaultOrg:
|
||||
features.LoginDefaultOrg.set(level, event.Value)
|
||||
case feature.KeyTriggerIntrospectionProjections:
|
||||
features.TriggerIntrospectionProjections.set(level, event.Value)
|
||||
case feature.KeyLegacyIntrospection:
|
||||
features.LegacyIntrospection.set(level, event.Value)
|
||||
case feature.KeyUserSchema:
|
||||
features.UserSchema.set(level, event.Value)
|
||||
case feature.KeyTokenExchange:
|
||||
|
@@ -75,10 +75,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -97,10 +93,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceUserSchemaEventType, false,
|
||||
@@ -120,10 +112,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: false,
|
||||
@@ -146,10 +134,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceUserSchemaEventType, false,
|
||||
@@ -177,10 +161,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
@@ -199,10 +179,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
ctx, aggregate,
|
||||
feature_v2.InstanceUserSchemaEventType, false,
|
||||
@@ -230,10 +206,6 @@ func TestQueries_GetInstanceFeatures(t *testing.T) {
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
|
@@ -68,10 +68,6 @@ func (*instanceFeatureProjection) Reducers() []handler.AggregateReducer {
|
||||
Event: feature_v2.InstanceTriggerIntrospectionProjectionsEventType,
|
||||
Reduce: reduceInstanceSetFeature[bool],
|
||||
},
|
||||
{
|
||||
Event: feature_v2.InstanceLegacyIntrospectionEventType,
|
||||
Reduce: reduceInstanceSetFeature[bool],
|
||||
},
|
||||
{
|
||||
Event: feature_v2.InstanceUserSchemaEventType,
|
||||
Reduce: reduceInstanceSetFeature[bool],
|
||||
|
@@ -26,7 +26,7 @@ func TestInstanceFeaturesProjection_reduces(t *testing.T) {
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
feature_v2.InstanceLegacyIntrospectionEventType,
|
||||
feature_v2.SystemUserSchemaEventType,
|
||||
feature_v2.AggregateType,
|
||||
[]byte(`{"value": true}`),
|
||||
), eventstore.GenericEventMapper[feature_v2.SetEvent[bool]]),
|
||||
@@ -41,7 +41,7 @@ func TestInstanceFeaturesProjection_reduces(t *testing.T) {
|
||||
expectedStmt: "INSERT INTO projections.instance_features2 (instance_id, key, creation_date, change_date, sequence, value) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (instance_id, key) DO UPDATE SET (creation_date, change_date, sequence, value) = (projections.instance_features2.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.value)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"legacy_introspection",
|
||||
"user_schema",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@@ -60,10 +60,6 @@ func (*systemFeatureProjection) Reducers() []handler.AggregateReducer {
|
||||
Event: feature_v2.SystemTriggerIntrospectionProjectionsEventType,
|
||||
Reduce: reduceSystemSetFeature[bool],
|
||||
},
|
||||
{
|
||||
Event: feature_v2.SystemLegacyIntrospectionEventType,
|
||||
Reduce: reduceSystemSetFeature[bool],
|
||||
},
|
||||
{
|
||||
Event: feature_v2.SystemUserSchemaEventType,
|
||||
Reduce: reduceSystemSetFeature[bool],
|
||||
|
@@ -24,7 +24,7 @@ func TestSystemFeaturesProjection_reduces(t *testing.T) {
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
feature_v2.SystemLegacyIntrospectionEventType,
|
||||
feature_v2.SystemUserSchemaEventType,
|
||||
feature_v2.AggregateType,
|
||||
[]byte(`{"value": true}`),
|
||||
), eventstore.GenericEventMapper[feature_v2.SetEvent[bool]]),
|
||||
@@ -38,7 +38,7 @@ func TestSystemFeaturesProjection_reduces(t *testing.T) {
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.system_features (key, creation_date, change_date, sequence, value) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (key) DO UPDATE SET (creation_date, change_date, sequence, value) = (projections.system_features.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.value)",
|
||||
expectedArgs: []interface{}{
|
||||
"legacy_introspection",
|
||||
"user_schema",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@@ -22,7 +22,6 @@ type SystemFeatures struct {
|
||||
|
||||
LoginDefaultOrg FeatureSource[bool]
|
||||
TriggerIntrospectionProjections FeatureSource[bool]
|
||||
LegacyIntrospection FeatureSource[bool]
|
||||
UserSchema FeatureSource[bool]
|
||||
TokenExchange FeatureSource[bool]
|
||||
ImprovedPerformance FeatureSource[[]feature.ImprovedPerformanceType]
|
||||
|
@@ -57,7 +57,6 @@ func (m *SystemFeaturesReadModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.SystemResetEventType,
|
||||
feature_v2.SystemLoginDefaultOrgEventType,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType,
|
||||
feature_v2.SystemLegacyIntrospectionEventType,
|
||||
feature_v2.SystemUserSchemaEventType,
|
||||
feature_v2.SystemTokenExchangeEventType,
|
||||
feature_v2.SystemImprovedPerformanceEventType,
|
||||
@@ -81,15 +80,12 @@ func reduceSystemFeatureSet[T any](features *SystemFeatures, event *feature_v2.S
|
||||
return err
|
||||
}
|
||||
switch key {
|
||||
case feature.KeyUnspecified,
|
||||
feature.KeyActionsDeprecated:
|
||||
case feature.KeyUnspecified:
|
||||
return nil
|
||||
case feature.KeyLoginDefaultOrg:
|
||||
features.LoginDefaultOrg.set(level, event.Value)
|
||||
case feature.KeyTriggerIntrospectionProjections:
|
||||
features.TriggerIntrospectionProjections.set(level, event.Value)
|
||||
case feature.KeyLegacyIntrospection:
|
||||
features.LegacyIntrospection.set(level, event.Value)
|
||||
case feature.KeyUserSchema:
|
||||
features.UserSchema.set(level, event.Value)
|
||||
case feature.KeyTokenExchange:
|
||||
|
@@ -53,10 +53,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemUserSchemaEventType, false,
|
||||
@@ -75,10 +71,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: false,
|
||||
@@ -97,10 +89,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemUserSchemaEventType, false,
|
||||
@@ -127,10 +115,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
@@ -149,10 +133,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemTriggerIntrospectionProjectionsEventType, true,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemLegacyIntrospectionEventType, false,
|
||||
)),
|
||||
eventFromEventPusher(feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemUserSchemaEventType, false,
|
||||
@@ -179,10 +159,6 @@ func TestQueries_GetSystemFeatures(t *testing.T) {
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
LegacyIntrospection: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
},
|
||||
UserSchema: FeatureSource[bool]{
|
||||
Level: feature.LevelUnspecified,
|
||||
Value: false,
|
||||
|
@@ -78,14 +78,6 @@ func NewUserGrantProjectIDSearchQuery(id string) (SearchQuery, error) {
|
||||
return NewTextQuery(UserGrantProjectID, id, TextEquals)
|
||||
}
|
||||
|
||||
func NewUserGrantProjectIDsSearchQuery(ids []string) (SearchQuery, error) {
|
||||
list := make([]interface{}, len(ids))
|
||||
for i, value := range ids {
|
||||
list[i] = value
|
||||
}
|
||||
return NewListQuery(UserGrantProjectID, list, ListIn)
|
||||
}
|
||||
|
||||
func NewUserGrantProjectOwnerSearchQuery(id string) (SearchQuery, error) {
|
||||
return NewTextQuery(ProjectColumnResourceOwner, id, TextEquals)
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemResetEventType, eventstore.GenericEventMapper[ResetEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemLoginDefaultOrgEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemTriggerIntrospectionProjectionsEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemLegacyIntrospectionEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemUserSchemaEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemTokenExchangeEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, SystemImprovedPerformanceEventType, eventstore.GenericEventMapper[SetEvent[[]feature.ImprovedPerformanceType]])
|
||||
@@ -22,7 +21,6 @@ func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceResetEventType, eventstore.GenericEventMapper[ResetEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceLoginDefaultOrgEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceTriggerIntrospectionProjectionsEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceLegacyIntrospectionEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceUserSchemaEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceTokenExchangeEventType, eventstore.GenericEventMapper[SetEvent[bool]])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, InstanceImprovedPerformanceEventType, eventstore.GenericEventMapper[SetEvent[[]feature.ImprovedPerformanceType]])
|
||||
|
@@ -14,7 +14,6 @@ var (
|
||||
SystemResetEventType = resetEventTypeFromFeature(feature.LevelSystem)
|
||||
SystemLoginDefaultOrgEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyLoginDefaultOrg)
|
||||
SystemTriggerIntrospectionProjectionsEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyTriggerIntrospectionProjections)
|
||||
SystemLegacyIntrospectionEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyLegacyIntrospection)
|
||||
SystemUserSchemaEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyUserSchema)
|
||||
SystemTokenExchangeEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyTokenExchange)
|
||||
SystemImprovedPerformanceEventType = setEventTypeFromFeature(feature.LevelSystem, feature.KeyImprovedPerformance)
|
||||
@@ -27,7 +26,6 @@ var (
|
||||
InstanceResetEventType = resetEventTypeFromFeature(feature.LevelInstance)
|
||||
InstanceLoginDefaultOrgEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyLoginDefaultOrg)
|
||||
InstanceTriggerIntrospectionProjectionsEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyTriggerIntrospectionProjections)
|
||||
InstanceLegacyIntrospectionEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyLegacyIntrospection)
|
||||
InstanceUserSchemaEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyUserSchema)
|
||||
InstanceTokenExchangeEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyTokenExchange)
|
||||
InstanceImprovedPerformanceEventType = setEventTypeFromFeature(feature.LevelInstance, feature.KeyImprovedPerformance)
|
||||
|
Reference in New Issue
Block a user