mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-04 23:45:07 +00:00
Merge branch 'next' into next-rc
This commit is contained in:
commit
e857e6794a
@ -211,11 +211,11 @@ Caches:
|
||||
# host:port address.
|
||||
Addr: localhost:6379
|
||||
# ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
|
||||
ClientName: ZITADEL_cache
|
||||
ClientName: ""
|
||||
# Use the specified Username to authenticate the current connection
|
||||
# with one of the connections defined in the ACL list when connecting
|
||||
# to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
|
||||
Username: zitadel
|
||||
Username: ""
|
||||
# Optional password. Must match the password specified in the
|
||||
# requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower),
|
||||
# or the User Password when connecting to a Redis 6.0 instance, or greater,
|
||||
|
@ -5,13 +5,16 @@ import (
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
cryptoDatabase "github.com/zitadel/zitadel/internal/crypto/database"
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/database/dialect"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
)
|
||||
|
||||
func verifyCmd() *cobra.Command {
|
||||
@ -98,12 +101,22 @@ func getViews(ctx context.Context, dest *database.DB, schema string) (tables []s
|
||||
}
|
||||
|
||||
func countEntries(ctx context.Context, client *database.DB, table string) (count int) {
|
||||
instanceClause := instanceClause()
|
||||
noInstanceIDColumn := []string{
|
||||
projection.InstanceProjectionTable,
|
||||
projection.SystemFeatureTable,
|
||||
cryptoDatabase.EncryptionKeysTable,
|
||||
}
|
||||
if slices.Contains(noInstanceIDColumn, table) {
|
||||
instanceClause = ""
|
||||
}
|
||||
|
||||
err := client.QueryRowContext(
|
||||
ctx,
|
||||
func(r *sql.Row) error {
|
||||
return r.Scan(&count)
|
||||
},
|
||||
fmt.Sprintf("SELECT COUNT(*) FROM %s %s", table, instanceClause()),
|
||||
fmt.Sprintf("SELECT COUNT(*) FROM %s %s", table, instanceClause),
|
||||
)
|
||||
logging.WithFields("table", table, "db", client.DatabaseName()).OnError(err).Error("unable to count")
|
||||
|
||||
|
@ -42,7 +42,7 @@ func (s *Server) ExportData(ctx context.Context, req *admin_pb.ExportDataRequest
|
||||
}
|
||||
|
||||
orgs := make([]*admin_pb.DataOrg, len(queriedOrgs.Orgs))
|
||||
processedOrgs := make([]string, len(queriedOrgs.Orgs))
|
||||
processedOrgs := make([]string, 0, len(queriedOrgs.Orgs))
|
||||
processedProjects := make([]string, 0)
|
||||
processedGrants := make([]string, 0)
|
||||
processedUsers := make([]string, 0)
|
||||
|
@ -8,9 +8,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/crewjam/saml"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
@ -49,6 +51,7 @@ const (
|
||||
paramError = "error"
|
||||
paramErrorDescription = "error_description"
|
||||
varIDPID = "idpid"
|
||||
paramInternalUI = "internalUI"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
@ -187,21 +190,8 @@ func (h *Handler) handleMetadata(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
metadata := sp.ServiceProvider.Metadata()
|
||||
|
||||
for i, spDesc := range metadata.SPSSODescriptors {
|
||||
spDesc.AssertionConsumerServices = append(
|
||||
spDesc.AssertionConsumerServices,
|
||||
saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: len(spDesc.AssertionConsumerServices) + 1,
|
||||
}, saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: len(spDesc.AssertionConsumerServices) + 2,
|
||||
},
|
||||
)
|
||||
metadata.SPSSODescriptors[i] = spDesc
|
||||
}
|
||||
internalUI, _ := strconv.ParseBool(r.URL.Query().Get(paramInternalUI))
|
||||
h.assertionConsumerServices(ctx, metadata, internalUI)
|
||||
|
||||
buf, _ := xml.MarshalIndent(metadata, "", " ")
|
||||
w.Header().Set("Content-Type", "application/samlmetadata+xml")
|
||||
@ -212,6 +202,48 @@ func (h *Handler) handleMetadata(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) assertionConsumerServices(ctx context.Context, metadata *saml.EntityDescriptor, internalUI bool) {
|
||||
if !internalUI {
|
||||
for i, spDesc := range metadata.SPSSODescriptors {
|
||||
spDesc.AssertionConsumerServices = append(
|
||||
spDesc.AssertionConsumerServices,
|
||||
saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: len(spDesc.AssertionConsumerServices) + 1,
|
||||
}, saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: len(spDesc.AssertionConsumerServices) + 2,
|
||||
},
|
||||
)
|
||||
metadata.SPSSODescriptors[i] = spDesc
|
||||
}
|
||||
return
|
||||
}
|
||||
for i, spDesc := range metadata.SPSSODescriptors {
|
||||
acs := make([]saml.IndexedEndpoint, 0, len(spDesc.AssertionConsumerServices)+2)
|
||||
acs = append(acs,
|
||||
saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: 0,
|
||||
IsDefault: gu.Ptr(true),
|
||||
},
|
||||
saml.IndexedEndpoint{
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: h.loginSAMLRootURL(ctx),
|
||||
Index: 1,
|
||||
})
|
||||
for i := 0; i < len(spDesc.AssertionConsumerServices); i++ {
|
||||
spDesc.AssertionConsumerServices[i].Index = 2 + i
|
||||
acs = append(acs, spDesc.AssertionConsumerServices[i])
|
||||
}
|
||||
spDesc.AssertionConsumerServices = acs
|
||||
metadata.SPSSODescriptors[i] = spDesc
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleACS(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
data := parseSAMLRequest(r)
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
saml_xml "github.com/zitadel/saml/pkg/provider/xml"
|
||||
"github.com/zitadel/saml/pkg/provider/xml/md"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
@ -111,13 +112,15 @@ func TestServer_SAMLMetadata(t *testing.T) {
|
||||
oauthIdpResp := Instance.AddGenericOAuthProvider(CTX, Instance.DefaultOrg.Id)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
idpID string
|
||||
ctx context.Context
|
||||
idpID string
|
||||
internalUI bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
wantACS []md.IndexedEndpointType
|
||||
}{
|
||||
{
|
||||
name: "saml metadata, invalid idp",
|
||||
@ -142,11 +145,115 @@ func TestServer_SAMLMetadata(t *testing.T) {
|
||||
idpID: samlRedirectIdpID,
|
||||
},
|
||||
want: http.StatusOK,
|
||||
wantACS: []md.IndexedEndpointType{
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "1",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + samlRedirectIdpID + "/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "2",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + samlRedirectIdpID + "/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "3",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/ui/login/login/externalidp/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "4",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/ui/login/login/externalidp/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "saml metadata, ok (internalUI)",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
idpID: samlRedirectIdpID,
|
||||
internalUI: true,
|
||||
},
|
||||
want: http.StatusOK,
|
||||
wantACS: []md.IndexedEndpointType{
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "0",
|
||||
IsDefault: "true",
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/ui/login/login/externalidp/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "1",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/ui/login/login/externalidp/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "2",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPPostBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + samlRedirectIdpID + "/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
{
|
||||
XMLName: xml.Name{
|
||||
Space: "urn:oasis:names:tc:SAML:2.0:metadata",
|
||||
Local: "AssertionConsumerService",
|
||||
},
|
||||
Index: "3",
|
||||
IsDefault: "",
|
||||
Binding: saml.HTTPArtifactBinding,
|
||||
Location: http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + samlRedirectIdpID + "/saml/acs",
|
||||
ResponseLocation: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
metadataURL := http_util.BuildOrigin(Instance.Host(), Instance.Config.Secure) + "/idps/" + tt.args.idpID + "/saml/metadata"
|
||||
if tt.args.internalUI {
|
||||
metadataURL = metadataURL + "?internalUI=true"
|
||||
}
|
||||
resp, err := http.Get(metadataURL)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, resp.StatusCode)
|
||||
@ -155,10 +262,11 @@ func TestServer_SAMLMetadata(t *testing.T) {
|
||||
defer resp.Body.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = saml_xml.ParseMetadataXmlIntoStruct(b)
|
||||
metadata, err := saml_xml.ParseMetadataXmlIntoStruct(b)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, metadata.SPSSODescriptor.AssertionConsumerService, tt.wantACS)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -600,6 +600,7 @@ func (s *Server) authResponseToken(authReq *AuthRequest, authorizer op.Authorize
|
||||
nil,
|
||||
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
||||
authReq.SessionID,
|
||||
authReq.oidc().ResponseType,
|
||||
)
|
||||
if err != nil {
|
||||
op.AuthRequestError(w, r, authReq, err, authorizer)
|
||||
|
@ -47,6 +47,7 @@ func (s *Server) ClientCredentialsExchange(ctx context.Context, r *op.ClientRequ
|
||||
nil,
|
||||
false,
|
||||
"",
|
||||
domain.OIDCResponseTypeUnspecified,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -87,6 +87,7 @@ func (s *Server) codeExchangeV1(ctx context.Context, client *Client, req *oidc.A
|
||||
nil,
|
||||
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
||||
authReq.SessionID,
|
||||
authReq.oidc().ResponseType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -300,6 +300,7 @@ func (s *Server) createExchangeAccessToken(
|
||||
actor,
|
||||
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
||||
"",
|
||||
domain.OIDCResponseTypeUnspecified,
|
||||
)
|
||||
if err != nil {
|
||||
return "", "", "", 0, err
|
||||
@ -346,6 +347,7 @@ func (s *Server) createExchangeJWT(
|
||||
actor,
|
||||
slices.Contains(scope, oidc.ScopeOfflineAccess),
|
||||
"",
|
||||
domain.OIDCResponseTypeUnspecified,
|
||||
)
|
||||
accessToken, err = s.createJWT(ctx, client, session, getUserInfo, roleAssertion, getSigner)
|
||||
if err != nil {
|
||||
|
@ -57,6 +57,7 @@ func (s *Server) JWTProfile(ctx context.Context, r *op.Request[oidc.JWTProfileGr
|
||||
nil,
|
||||
false,
|
||||
"",
|
||||
domain.OIDCResponseTypeUnspecified,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -69,6 +69,7 @@ func (s *Server) refreshTokenV1(ctx context.Context, client *Client, r *op.Clien
|
||||
refreshToken.Actor,
|
||||
true,
|
||||
"",
|
||||
domain.OIDCResponseTypeUnspecified,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -147,6 +147,7 @@ func (c *Commands) CreateOIDCSession(ctx context.Context,
|
||||
actor *domain.TokenActor,
|
||||
needRefreshToken bool,
|
||||
sessionID string,
|
||||
responseType domain.OIDCResponseType,
|
||||
) (session *OIDCSession, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
@ -164,8 +165,10 @@ func (c *Commands) CreateOIDCSession(ctx context.Context,
|
||||
|
||||
cmd.AddSession(ctx, userID, resourceOwner, sessionID, clientID, audience, scope, authMethods, authTime, nonce, preferredLanguage, userAgent)
|
||||
cmd.RegisterLogout(ctx, sessionID, userID, clientID, backChannelLogoutURI)
|
||||
if err = cmd.AddAccessToken(ctx, scope, userID, resourceOwner, reason, actor); err != nil {
|
||||
return nil, err
|
||||
if responseType != domain.OIDCResponseTypeIDToken {
|
||||
if err = cmd.AddAccessToken(ctx, scope, userID, resourceOwner, reason, actor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if needRefreshToken {
|
||||
if err = cmd.AddRefreshToken(ctx, userID); err != nil {
|
||||
|
@ -749,6 +749,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
actor *domain.TokenActor
|
||||
needRefreshToken bool
|
||||
sessionID string
|
||||
responseType domain.OIDCResponseType
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -788,6 +789,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
@ -844,6 +846,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
wantErr: zerrors.ThrowPreconditionFailed(nil, "OIDCS-kj3g2", "Errors.User.NotActive"),
|
||||
},
|
||||
@ -918,6 +921,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
@ -943,6 +947,87 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ID token only",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
user.NewHumanAddedEvent(
|
||||
context.Background(),
|
||||
&user.NewAggregate("userID", "org1").Aggregate,
|
||||
"username",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.Afrikaans,
|
||||
domain.GenderUnspecified,
|
||||
"email",
|
||||
false,
|
||||
),
|
||||
),
|
||||
expectFilter(), // token lifetime
|
||||
expectPush(
|
||||
oidcsession.NewAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
|
||||
"userID", "org1", "", "clientID", []string{"audience"}, []string{"openid", "offline_access"},
|
||||
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword}, testNow, "nonce", &language.Afrikaans,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: mock.NewIDGeneratorExpectIDs(t, "oidcSessionID"),
|
||||
defaultAccessTokenLifetime: time.Hour,
|
||||
defaultRefreshTokenLifetime: 7 * 24 * time.Hour,
|
||||
defaultRefreshTokenIdleLifetime: 24 * time.Hour,
|
||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instanceID"),
|
||||
userID: "userID",
|
||||
resourceOwner: "org1",
|
||||
clientID: "clientID",
|
||||
audience: []string{"audience"},
|
||||
scope: []string{"openid", "offline_access"},
|
||||
authMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
||||
authTime: testNow,
|
||||
nonce: "nonce",
|
||||
preferredLanguage: &language.Afrikaans,
|
||||
userAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
reason: domain.TokenReasonAuthRequest,
|
||||
actor: &domain.TokenActor{
|
||||
UserID: "user2",
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeIDToken,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
ClientID: "clientID",
|
||||
UserID: "userID",
|
||||
Audience: []string{"audience"},
|
||||
Scope: []string{"openid", "offline_access"},
|
||||
AuthMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
||||
AuthTime: testNow,
|
||||
Nonce: "nonce",
|
||||
PreferredLanguage: &language.Afrikaans,
|
||||
UserAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disable user token event",
|
||||
fields: fields{
|
||||
@ -1018,6 +1103,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
@ -1115,6 +1201,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: true,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
@ -1213,6 +1300,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
},
|
||||
needRefreshToken: false,
|
||||
sessionID: "sessionID",
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
@ -1594,6 +1682,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
wantErr: zerrors.ThrowPermissionDenied(nil, "test", "test"),
|
||||
},
|
||||
@ -1675,6 +1764,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
responseType: domain.OIDCResponseTypeUnspecified,
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
@ -1729,6 +1819,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
tt.args.actor,
|
||||
tt.args.needRefreshToken,
|
||||
tt.args.sessionID,
|
||||
tt.args.responseType,
|
||||
)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
if got != nil {
|
||||
|
@ -2,7 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"slices"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
@ -47,7 +47,7 @@ func (c *Commands) SetTriggerActions(ctx context.Context, flowType domain.FlowTy
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reflect.DeepEqual(existingFlow.Triggers[triggerType], actionIDs) {
|
||||
if slices.Equal(existingFlow.Triggers[triggerType], actionIDs) {
|
||||
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-Nfh52", "Errors.Flow.NoChanges")
|
||||
}
|
||||
if len(actionIDs) > 0 {
|
||||
|
@ -448,7 +448,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if existing.UserState != domain.UserStateUnspecified {
|
||||
if existing.UserState.Exists() {
|
||||
return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-ziuna", "Errors.User.AlreadyExisting")
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,8 @@ const (
|
||||
type OIDCResponseType int32
|
||||
|
||||
const (
|
||||
OIDCResponseTypeCode OIDCResponseType = iota
|
||||
OIDCResponseTypeUnspecified OIDCResponseType = iota - 1 // Negative offset not to break existing configs.
|
||||
OIDCResponseTypeCode
|
||||
OIDCResponseTypeIDToken
|
||||
OIDCResponseTypeIDTokenToken
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ type StepStates struct {
|
||||
// Query implements eventstore.QueryReducer.
|
||||
func (*StepStates) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
InstanceID(""). // to make sure we can use an appropriate index
|
||||
AddQuery().
|
||||
AggregateTypes(SystemAggregate).
|
||||
AggregateIDs(SystemAggregateID).
|
||||
|
@ -168,6 +168,7 @@ func prepareTriggerActionsQuery(ctx context.Context, db prepareDatabase) (sq.Sel
|
||||
).
|
||||
From(flowsTriggersTable.name).
|
||||
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
|
||||
OrderBy(FlowsTriggersColumnTriggerSequence.identifier()).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) ([]*Action, error) {
|
||||
actions := make([]*Action, 0)
|
||||
@ -220,6 +221,7 @@ func prepareFlowQuery(ctx context.Context, db prepareDatabase, flowType domain.F
|
||||
).
|
||||
From(flowsTriggersTable.name).
|
||||
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
|
||||
OrderBy(FlowsTriggersColumnTriggerSequence.identifier()).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*Flow, error) {
|
||||
flow := &Flow{
|
||||
|
@ -33,8 +33,9 @@ var (
|
||||
` projections.flow_triggers3.sequence,` +
|
||||
` projections.flow_triggers3.resource_owner` +
|
||||
` FROM projections.flow_triggers3` +
|
||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers3.action_id = projections.actions3.id AND projections.flow_triggers3.instance_id = projections.actions3.instance_id`
|
||||
// ` AS OF SYSTEM TIME '-1 ms'`
|
||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers3.action_id = projections.actions3.id AND projections.flow_triggers3.instance_id = projections.actions3.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'` +
|
||||
` ORDER BY projections.flow_triggers3.trigger_sequence`
|
||||
prepareFlowCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@ -66,8 +67,9 @@ var (
|
||||
` projections.actions3.allowed_to_fail,` +
|
||||
` projections.actions3.timeout` +
|
||||
` FROM projections.flow_triggers3` +
|
||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers3.action_id = projections.actions3.id AND projections.flow_triggers3.instance_id = projections.actions3.instance_id`
|
||||
// ` AS OF SYSTEM TIME '-1 ms'`
|
||||
` LEFT JOIN projections.actions3 ON projections.flow_triggers3.action_id = projections.actions3.id AND projections.flow_triggers3.instance_id = projections.actions3.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'` +
|
||||
` ORDER BY projections.flow_triggers3.trigger_sequence`
|
||||
|
||||
prepareTriggerActionCols = []string{
|
||||
"id",
|
||||
|
Loading…
Reference in New Issue
Block a user