feat(OIDC): add back channel logout (#8837)

# Which Problems Are Solved

Currently ZITADEL supports RP-initiated logout for clients. Back-channel
logout ensures that user sessions are terminated across all connected
applications, even if the user closes their browser or loses
connectivity providing a more secure alternative for certain use cases.

# How the Problems Are Solved

If the feature is activated and the client used for the authentication
has a back_channel_logout_uri configured, a
`session_logout.back_channel` will be registered. Once a user terminates
their session, a (notification) handler will send a SET (form POST) to
the registered uri containing a logout_token (with the user's ID and
session ID).

- A new feature "back_channel_logout" is added on system and instance
level
- A `back_channel_logout_uri` can be managed on OIDC applications
- Added a `session_logout` aggregate to register and inform about sent
`back_channel` notifications
- Added a `SecurityEventToken` channel and `Form`message type in the
notification handlers
- Added `TriggeredAtOrigin` fields to `HumanSignedOut` and
`TerminateSession` events for notification handling
- Exported various functions and types in the `oidc` package to be able
to reuse for token signing in the back_channel notifier.
- To prevent that current existing session termination events will be
handled, a setup step is added to set the `current_states` for the
`projections.notifications_back_channel_logout` to the current position

- [x] requires https://github.com/zitadel/oidc/pull/671

# Additional Changes

- Updated all OTEL dependencies to v1.29.0, since OIDC already updated
some of them to that version.
- Single Session Termination feature is correctly checked (fixed feature
mapping)

# Additional Context

- closes https://github.com/zitadel/zitadel/issues/8467
- TODO:
  - Documentation
  - UI to be done: https://github.com/zitadel/zitadel/issues/8469

---------

Co-authored-by: Hidde Wieringa <hidde@hiddewieringa.nl>
This commit is contained in:
Livio Spring
2024-10-31 15:57:17 +01:00
committed by GitHub
parent 9cf67f30b8
commit 041af26917
87 changed files with 1778 additions and 280 deletions

View File

@@ -6,6 +6,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/notification/channels/email"
"github.com/zitadel/zitadel/internal/notification/channels/set"
"github.com/zitadel/zitadel/internal/notification/channels/sms"
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
"github.com/zitadel/zitadel/internal/notification/handlers"
@@ -104,3 +105,14 @@ func (c *channels) Webhook(ctx context.Context, cfg webhook.Config) (*senders.Ch
c.counters.failed.json,
)
}
func (c *channels) SecurityTokenEvent(ctx context.Context, cfg set.Config) (*senders.Chain, error) {
return senders.SecurityEventTokenChannels(
ctx,
cfg,
c.q.GetFileSystemProvider,
c.q.GetLogProvider,
c.counters.success.json,
c.counters.failed.json,
)
}

View File

@@ -0,0 +1,75 @@
package set
import (
"context"
"encoding/json"
"io"
"net/http"
"strings"
"time"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/notification/channels"
"github.com/zitadel/zitadel/internal/notification/messages"
"github.com/zitadel/zitadel/internal/zerrors"
)
func InitChannel(ctx context.Context, cfg Config) (channels.NotificationChannel, error) {
if err := cfg.Validate(); err != nil {
return nil, err
}
logging.Debug("successfully initialized security event token json channel")
return channels.HandleMessageFunc(func(message channels.Message) error {
requestCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
msg, ok := message.(*messages.Form)
if !ok {
return zerrors.ThrowInternal(nil, "SET-K686U", "message is not SET")
}
payload, err := msg.GetContent()
if err != nil {
return err
}
req, err := http.NewRequestWithContext(requestCtx, http.MethodPost, cfg.CallURL, strings.NewReader(payload))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
logging.WithFields("instanceID", authz.GetInstance(ctx).InstanceID(), "calling_url", cfg.CallURL).Debug("security event token called")
if resp.StatusCode == http.StatusOK ||
resp.StatusCode == http.StatusAccepted ||
resp.StatusCode == http.StatusNoContent {
return nil
}
body, err := mapResponse(resp)
logging.WithFields("instanceID", authz.GetInstance(ctx).InstanceID(), "callURL", cfg.CallURL).
OnError(err).Debug("error mapping response")
if resp.StatusCode == http.StatusBadRequest {
logging.WithFields("instanceID", authz.GetInstance(ctx).InstanceID(), "callURL", cfg.CallURL, "status", resp.Status, "body", body).
Error("security event token didn't return a success status")
return nil
}
return zerrors.ThrowInternalf(err, "SET-DF3dq", "security event token to %s didn't return a success status: %s (%v)", cfg.CallURL, resp.Status, body)
}), nil
}
func mapResponse(resp *http.Response) (map[string]any, error) {
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
requestError := make(map[string]any)
err = json.Unmarshal(body, &requestError)
if err != nil {
return nil, err
}
return requestError, nil
}

View File

@@ -0,0 +1,14 @@
package set
import (
"net/url"
)
type Config struct {
CallURL string
}
func (w *Config) Validate() error {
_, err := url.Parse(w.CallURL)
return err
}

View File

@@ -0,0 +1,266 @@
package handlers
import (
"context"
"errors"
"slices"
"sync"
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v3/pkg/crypto"
"github.com/zitadel/oidc/v3/pkg/oidc"
"github.com/zitadel/oidc/v3/pkg/op"
"github.com/zitadel/zitadel/internal/api/authz"
http_utils "github.com/zitadel/zitadel/internal/api/http"
zoidc "github.com/zitadel/zitadel/internal/api/oidc"
"github.com/zitadel/zitadel/internal/command"
zcrypto "github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
"github.com/zitadel/zitadel/internal/id"
"github.com/zitadel/zitadel/internal/notification/channels/set"
_ "github.com/zitadel/zitadel/internal/notification/statik"
"github.com/zitadel/zitadel/internal/notification/types"
"github.com/zitadel/zitadel/internal/repository/session"
"github.com/zitadel/zitadel/internal/repository/sessionlogout"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors"
)
const (
BackChannelLogoutNotificationsProjectionTable = "projections.notifications_back_channel_logout"
)
type backChannelLogoutNotifier struct {
commands *command.Commands
queries *NotificationQueries
eventstore *eventstore.Eventstore
keyEncryptionAlg zcrypto.EncryptionAlgorithm
channels types.ChannelChains
idGenerator id.Generator
tokenLifetime time.Duration
}
func NewBackChannelLogoutNotifier(
ctx context.Context,
config handler.Config,
commands *command.Commands,
queries *NotificationQueries,
es *eventstore.Eventstore,
keyEncryptionAlg zcrypto.EncryptionAlgorithm,
channels types.ChannelChains,
tokenLifetime time.Duration,
) *handler.Handler {
return handler.NewHandler(ctx, &config, &backChannelLogoutNotifier{
commands: commands,
queries: queries,
eventstore: es,
keyEncryptionAlg: keyEncryptionAlg,
channels: channels,
tokenLifetime: tokenLifetime,
idGenerator: id.SonyFlakeGenerator(),
})
}
func (*backChannelLogoutNotifier) Name() string {
return BackChannelLogoutNotificationsProjectionTable
}
func (u *backChannelLogoutNotifier) Reducers() []handler.AggregateReducer {
return []handler.AggregateReducer{
{
Aggregate: session.AggregateType,
EventReducers: []handler.EventReducer{
{
Event: session.TerminateType,
Reduce: u.reduceSessionTerminated,
},
},
}, {
Aggregate: user.AggregateType,
EventReducers: []handler.EventReducer{
{
Event: user.HumanSignedOutType,
Reduce: u.reduceUserSignedOut,
},
},
},
}
}
func (u *backChannelLogoutNotifier) reduceUserSignedOut(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.HumanSignedOutEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-Gr63h", "reduce.wrong.event.type %s", user.HumanSignedOutType)
}
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
ctx, err := u.queries.HandlerContext(event.Aggregate())
if err != nil {
return err
}
if !authz.GetFeatures(ctx).EnableBackChannelLogout {
return nil
}
if e.SessionID == "" {
return nil
}
return u.terminateSession(ctx, e.SessionID, e)
}), nil
}
func (u *backChannelLogoutNotifier) reduceSessionTerminated(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*session.TerminateEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-D6H2h", "reduce.wrong.event.type %s", session.TerminateType)
}
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
ctx, err := u.queries.HandlerContext(event.Aggregate())
if err != nil {
return err
}
if !authz.GetFeatures(ctx).EnableBackChannelLogout {
return nil
}
return u.terminateSession(ctx, e.Aggregate().ID, e)
}), nil
}
type backChannelLogoutSession struct {
sessionID string
// sessions contain a map of oidc session IDs and their corresponding clientID
sessions []backChannelLogoutOIDCSessions
}
func (u *backChannelLogoutNotifier) terminateSession(ctx context.Context, id string, e eventstore.Event) error {
sessions := &backChannelLogoutSession{sessionID: id}
err := u.eventstore.FilterToQueryReducer(ctx, sessions)
if err != nil {
return err
}
ctx, err = u.queries.Origin(ctx, e)
if err != nil {
return err
}
getSigner := zoidc.GetSignerOnce(u.queries.GetActiveSigningWebKey, u.signingKey)
var wg sync.WaitGroup
wg.Add(len(sessions.sessions))
errs := make([]error, 0, len(sessions.sessions))
for _, oidcSession := range sessions.sessions {
go func(oidcSession *backChannelLogoutOIDCSessions) {
defer wg.Done()
err := u.sendLogoutToken(ctx, oidcSession, e, getSigner)
if err != nil {
errs = append(errs, err)
return
}
err = u.commands.BackChannelLogoutSent(ctx, oidcSession.SessionID, oidcSession.OIDCSessionID, e.Aggregate().InstanceID)
if err != nil {
errs = append(errs, err)
}
}(&oidcSession)
}
wg.Wait()
return errors.Join(errs...)
}
func (u *backChannelLogoutNotifier) signingKey(ctx context.Context) (op.SigningKey, error) {
keys, err := u.queries.ActivePrivateSigningKey(ctx, time.Now())
if err != nil {
return nil, err
}
if len(keys.Keys) == 0 {
logging.WithFields("instanceID", authz.GetInstance(ctx).InstanceID()).
Info("There's no active signing key and automatic rotation is not supported for back channel logout." +
"Please enable the webkey management feature on your instance")
return nil, zerrors.ThrowPreconditionFailed(nil, "HANDL-DF3nf", "no active signing key")
}
return zoidc.PrivateKeyToSigningKey(zoidc.SelectSigningKey(keys.Keys), u.keyEncryptionAlg)
}
func (u *backChannelLogoutNotifier) sendLogoutToken(ctx context.Context, oidcSession *backChannelLogoutOIDCSessions, e eventstore.Event, getSigner zoidc.SignerFunc) error {
token, err := u.logoutToken(ctx, oidcSession, getSigner)
if err != nil {
return err
}
err = types.SendSecurityTokenEvent(ctx, set.Config{CallURL: oidcSession.BackChannelLogoutURI}, u.channels, &LogoutTokenMessage{LogoutToken: token}, e).WithoutTemplate()
if err != nil {
return err
}
return nil
}
func (u *backChannelLogoutNotifier) logoutToken(ctx context.Context, oidcSession *backChannelLogoutOIDCSessions, getSigner zoidc.SignerFunc) (string, error) {
jwtID, err := u.idGenerator.Next()
if err != nil {
return "", err
}
token := oidc.NewLogoutTokenClaims(
http_utils.DomainContext(ctx).Origin(),
oidcSession.UserID,
oidc.Audience{oidcSession.ClientID},
time.Now().Add(u.tokenLifetime),
jwtID,
oidcSession.SessionID,
time.Second,
)
signer, _, err := getSigner(ctx)
if err != nil {
return "", err
}
return crypto.Sign(token, signer)
}
type LogoutTokenMessage struct {
LogoutToken string `schema:"logout_token"`
}
type backChannelLogoutOIDCSessions struct {
SessionID string
OIDCSessionID string
UserID string
ClientID string
BackChannelLogoutURI string
}
func (b *backChannelLogoutSession) Reduce() error {
return nil
}
func (b *backChannelLogoutSession) AppendEvents(events ...eventstore.Event) {
for _, event := range events {
switch e := event.(type) {
case *sessionlogout.BackChannelLogoutRegisteredEvent:
b.sessions = append(b.sessions, backChannelLogoutOIDCSessions{
SessionID: b.sessionID,
OIDCSessionID: e.OIDCSessionID,
UserID: e.UserID,
ClientID: e.ClientID,
BackChannelLogoutURI: e.BackChannelLogoutURI,
})
case *sessionlogout.BackChannelLogoutSentEvent:
slices.DeleteFunc(b.sessions, func(session backChannelLogoutOIDCSessions) bool {
return session.OIDCSessionID == e.OIDCSessionID
})
}
}
}
func (b *backChannelLogoutSession) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
AddQuery().
AggregateTypes(sessionlogout.AggregateType).
AggregateIDs(b.sessionID).
EventTypes(
sessionlogout.BackChannelLogoutRegisteredType,
sessionlogout.BackChannelLogoutSentType).
Builder()
}

View File

@@ -13,3 +13,13 @@ func HandlerContext(event *eventstore.Aggregate) context.Context {
ctx := authz.WithInstanceID(context.Background(), event.InstanceID)
return authz.SetCtxData(ctx, authz.CtxData{UserID: NotifyUserID, OrgID: event.ResourceOwner})
}
func (n *NotificationQueries) HandlerContext(event *eventstore.Aggregate) (context.Context, error) {
ctx := context.Background()
instance, err := n.InstanceByID(ctx, event.InstanceID)
if err != nil {
return nil, err
}
ctx = authz.WithInstance(ctx, instance)
return authz.SetCtxData(ctx, authz.CtxData{UserID: NotifyUserID, OrgID: event.ResourceOwner}), nil
}

View File

@@ -23,6 +23,7 @@ import (
type MockCommands struct {
ctrl *gomock.Controller
recorder *MockCommandsMockRecorder
isgomock struct{}
}
// MockCommandsMockRecorder is the mock recorder for MockCommands.
@@ -43,197 +44,197 @@ func (m *MockCommands) EXPECT() *MockCommandsMockRecorder {
}
// HumanEmailVerificationCodeSent mocks base method.
func (m *MockCommands) HumanEmailVerificationCodeSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) HumanEmailVerificationCodeSent(ctx context.Context, orgID, userID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanEmailVerificationCodeSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "HumanEmailVerificationCodeSent", ctx, orgID, userID)
ret0, _ := ret[0].(error)
return ret0
}
// HumanEmailVerificationCodeSent indicates an expected call of HumanEmailVerificationCodeSent.
func (mr *MockCommandsMockRecorder) HumanEmailVerificationCodeSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanEmailVerificationCodeSent(ctx, orgID, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanEmailVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanEmailVerificationCodeSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanEmailVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanEmailVerificationCodeSent), ctx, orgID, userID)
}
// HumanInitCodeSent mocks base method.
func (m *MockCommands) HumanInitCodeSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) HumanInitCodeSent(ctx context.Context, orgID, userID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanInitCodeSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "HumanInitCodeSent", ctx, orgID, userID)
ret0, _ := ret[0].(error)
return ret0
}
// HumanInitCodeSent indicates an expected call of HumanInitCodeSent.
func (mr *MockCommandsMockRecorder) HumanInitCodeSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanInitCodeSent(ctx, orgID, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanInitCodeSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanInitCodeSent), ctx, orgID, userID)
}
// HumanOTPEmailCodeSent mocks base method.
func (m *MockCommands) HumanOTPEmailCodeSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) HumanOTPEmailCodeSent(ctx context.Context, userID, resourceOwner string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanOTPEmailCodeSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "HumanOTPEmailCodeSent", ctx, userID, resourceOwner)
ret0, _ := ret[0].(error)
return ret0
}
// HumanOTPEmailCodeSent indicates an expected call of HumanOTPEmailCodeSent.
func (mr *MockCommandsMockRecorder) HumanOTPEmailCodeSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanOTPEmailCodeSent(ctx, userID, resourceOwner any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPEmailCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPEmailCodeSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPEmailCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPEmailCodeSent), ctx, userID, resourceOwner)
}
// HumanOTPSMSCodeSent mocks base method.
func (m *MockCommands) HumanOTPSMSCodeSent(arg0 context.Context, arg1, arg2 string, arg3 *senders.CodeGeneratorInfo) error {
func (m *MockCommands) HumanOTPSMSCodeSent(ctx context.Context, userID, resourceOwner string, generatorInfo *senders.CodeGeneratorInfo) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanOTPSMSCodeSent", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "HumanOTPSMSCodeSent", ctx, userID, resourceOwner, generatorInfo)
ret0, _ := ret[0].(error)
return ret0
}
// HumanOTPSMSCodeSent indicates an expected call of HumanOTPSMSCodeSent.
func (mr *MockCommandsMockRecorder) HumanOTPSMSCodeSent(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanOTPSMSCodeSent(ctx, userID, resourceOwner, generatorInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPSMSCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPSMSCodeSent), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPSMSCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPSMSCodeSent), ctx, userID, resourceOwner, generatorInfo)
}
// HumanPasswordlessInitCodeSent mocks base method.
func (m *MockCommands) HumanPasswordlessInitCodeSent(arg0 context.Context, arg1, arg2, arg3 string) error {
func (m *MockCommands) HumanPasswordlessInitCodeSent(ctx context.Context, userID, resourceOwner, codeID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanPasswordlessInitCodeSent", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "HumanPasswordlessInitCodeSent", ctx, userID, resourceOwner, codeID)
ret0, _ := ret[0].(error)
return ret0
}
// HumanPasswordlessInitCodeSent indicates an expected call of HumanPasswordlessInitCodeSent.
func (mr *MockCommandsMockRecorder) HumanPasswordlessInitCodeSent(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanPasswordlessInitCodeSent(ctx, userID, resourceOwner, codeID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPasswordlessInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPasswordlessInitCodeSent), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPasswordlessInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPasswordlessInitCodeSent), ctx, userID, resourceOwner, codeID)
}
// HumanPhoneVerificationCodeSent mocks base method.
func (m *MockCommands) HumanPhoneVerificationCodeSent(arg0 context.Context, arg1, arg2 string, arg3 *senders.CodeGeneratorInfo) error {
func (m *MockCommands) HumanPhoneVerificationCodeSent(ctx context.Context, orgID, userID string, generatorInfo *senders.CodeGeneratorInfo) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HumanPhoneVerificationCodeSent", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "HumanPhoneVerificationCodeSent", ctx, orgID, userID, generatorInfo)
ret0, _ := ret[0].(error)
return ret0
}
// HumanPhoneVerificationCodeSent indicates an expected call of HumanPhoneVerificationCodeSent.
func (mr *MockCommandsMockRecorder) HumanPhoneVerificationCodeSent(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) HumanPhoneVerificationCodeSent(ctx, orgID, userID, generatorInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPhoneVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPhoneVerificationCodeSent), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPhoneVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPhoneVerificationCodeSent), ctx, orgID, userID, generatorInfo)
}
// InviteCodeSent mocks base method.
func (m *MockCommands) InviteCodeSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) InviteCodeSent(ctx context.Context, orgID, userID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InviteCodeSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "InviteCodeSent", ctx, orgID, userID)
ret0, _ := ret[0].(error)
return ret0
}
// InviteCodeSent indicates an expected call of InviteCodeSent.
func (mr *MockCommandsMockRecorder) InviteCodeSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) InviteCodeSent(ctx, orgID, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InviteCodeSent", reflect.TypeOf((*MockCommands)(nil).InviteCodeSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InviteCodeSent", reflect.TypeOf((*MockCommands)(nil).InviteCodeSent), ctx, orgID, userID)
}
// MilestonePushed mocks base method.
func (m *MockCommands) MilestonePushed(arg0 context.Context, arg1 string, arg2 milestone.Type, arg3 []string) error {
func (m *MockCommands) MilestonePushed(ctx context.Context, instanceID string, msType milestone.Type, endpoints []string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MilestonePushed", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "MilestonePushed", ctx, instanceID, msType, endpoints)
ret0, _ := ret[0].(error)
return ret0
}
// MilestonePushed indicates an expected call of MilestonePushed.
func (mr *MockCommandsMockRecorder) MilestonePushed(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) MilestonePushed(ctx, instanceID, msType, endpoints any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MilestonePushed", reflect.TypeOf((*MockCommands)(nil).MilestonePushed), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MilestonePushed", reflect.TypeOf((*MockCommands)(nil).MilestonePushed), ctx, instanceID, msType, endpoints)
}
// OTPEmailSent mocks base method.
func (m *MockCommands) OTPEmailSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) OTPEmailSent(ctx context.Context, sessionID, resourceOwner string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "OTPEmailSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "OTPEmailSent", ctx, sessionID, resourceOwner)
ret0, _ := ret[0].(error)
return ret0
}
// OTPEmailSent indicates an expected call of OTPEmailSent.
func (mr *MockCommandsMockRecorder) OTPEmailSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) OTPEmailSent(ctx, sessionID, resourceOwner any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPEmailSent", reflect.TypeOf((*MockCommands)(nil).OTPEmailSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPEmailSent", reflect.TypeOf((*MockCommands)(nil).OTPEmailSent), ctx, sessionID, resourceOwner)
}
// OTPSMSSent mocks base method.
func (m *MockCommands) OTPSMSSent(arg0 context.Context, arg1, arg2 string, arg3 *senders.CodeGeneratorInfo) error {
func (m *MockCommands) OTPSMSSent(ctx context.Context, sessionID, resourceOwner string, generatorInfo *senders.CodeGeneratorInfo) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "OTPSMSSent", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "OTPSMSSent", ctx, sessionID, resourceOwner, generatorInfo)
ret0, _ := ret[0].(error)
return ret0
}
// OTPSMSSent indicates an expected call of OTPSMSSent.
func (mr *MockCommandsMockRecorder) OTPSMSSent(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) OTPSMSSent(ctx, sessionID, resourceOwner, generatorInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPSMSSent", reflect.TypeOf((*MockCommands)(nil).OTPSMSSent), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPSMSSent", reflect.TypeOf((*MockCommands)(nil).OTPSMSSent), ctx, sessionID, resourceOwner, generatorInfo)
}
// PasswordChangeSent mocks base method.
func (m *MockCommands) PasswordChangeSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) PasswordChangeSent(ctx context.Context, orgID, userID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PasswordChangeSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "PasswordChangeSent", ctx, orgID, userID)
ret0, _ := ret[0].(error)
return ret0
}
// PasswordChangeSent indicates an expected call of PasswordChangeSent.
func (mr *MockCommandsMockRecorder) PasswordChangeSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) PasswordChangeSent(ctx, orgID, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordChangeSent", reflect.TypeOf((*MockCommands)(nil).PasswordChangeSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordChangeSent", reflect.TypeOf((*MockCommands)(nil).PasswordChangeSent), ctx, orgID, userID)
}
// PasswordCodeSent mocks base method.
func (m *MockCommands) PasswordCodeSent(arg0 context.Context, arg1, arg2 string, arg3 *senders.CodeGeneratorInfo) error {
func (m *MockCommands) PasswordCodeSent(ctx context.Context, orgID, userID string, generatorInfo *senders.CodeGeneratorInfo) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PasswordCodeSent", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "PasswordCodeSent", ctx, orgID, userID, generatorInfo)
ret0, _ := ret[0].(error)
return ret0
}
// PasswordCodeSent indicates an expected call of PasswordCodeSent.
func (mr *MockCommandsMockRecorder) PasswordCodeSent(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) PasswordCodeSent(ctx, orgID, userID, generatorInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordCodeSent", reflect.TypeOf((*MockCommands)(nil).PasswordCodeSent), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordCodeSent", reflect.TypeOf((*MockCommands)(nil).PasswordCodeSent), ctx, orgID, userID, generatorInfo)
}
// UsageNotificationSent mocks base method.
func (m *MockCommands) UsageNotificationSent(arg0 context.Context, arg1 *quota.NotificationDueEvent) error {
func (m *MockCommands) UsageNotificationSent(ctx context.Context, dueEvent *quota.NotificationDueEvent) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UsageNotificationSent", arg0, arg1)
ret := m.ctrl.Call(m, "UsageNotificationSent", ctx, dueEvent)
ret0, _ := ret[0].(error)
return ret0
}
// UsageNotificationSent indicates an expected call of UsageNotificationSent.
func (mr *MockCommandsMockRecorder) UsageNotificationSent(arg0, arg1 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) UsageNotificationSent(ctx, dueEvent any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UsageNotificationSent", reflect.TypeOf((*MockCommands)(nil).UsageNotificationSent), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UsageNotificationSent", reflect.TypeOf((*MockCommands)(nil).UsageNotificationSent), ctx, dueEvent)
}
// UserDomainClaimedSent mocks base method.
func (m *MockCommands) UserDomainClaimedSent(arg0 context.Context, arg1, arg2 string) error {
func (m *MockCommands) UserDomainClaimedSent(ctx context.Context, orgID, userID string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UserDomainClaimedSent", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "UserDomainClaimedSent", ctx, orgID, userID)
ret0, _ := ret[0].(error)
return ret0
}
// UserDomainClaimedSent indicates an expected call of UserDomainClaimedSent.
func (mr *MockCommandsMockRecorder) UserDomainClaimedSent(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockCommandsMockRecorder) UserDomainClaimedSent(ctx, orgID, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserDomainClaimedSent", reflect.TypeOf((*MockCommands)(nil).UserDomainClaimedSent), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserDomainClaimedSent", reflect.TypeOf((*MockCommands)(nil).UserDomainClaimedSent), ctx, orgID, userID)
}

View File

@@ -12,7 +12,10 @@ package mock
import (
context "context"
reflect "reflect"
time "time"
jose "github.com/go-jose/go-jose/v4"
authz "github.com/zitadel/zitadel/internal/api/authz"
domain "github.com/zitadel/zitadel/internal/domain"
query "github.com/zitadel/zitadel/internal/query"
gomock "go.uber.org/mock/gomock"
@@ -23,6 +26,7 @@ import (
type MockQueries struct {
ctrl *gomock.Controller
recorder *MockQueriesMockRecorder
isgomock struct{}
}
// MockQueriesMockRecorder is the mock recorder for MockQueries.
@@ -43,195 +47,240 @@ func (m *MockQueries) EXPECT() *MockQueriesMockRecorder {
}
// ActiveLabelPolicyByOrg mocks base method.
func (m *MockQueries) ActiveLabelPolicyByOrg(arg0 context.Context, arg1 string, arg2 bool) (*query.LabelPolicy, error) {
func (m *MockQueries) ActiveLabelPolicyByOrg(ctx context.Context, orgID string, withOwnerRemoved bool) (*query.LabelPolicy, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ActiveLabelPolicyByOrg", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "ActiveLabelPolicyByOrg", ctx, orgID, withOwnerRemoved)
ret0, _ := ret[0].(*query.LabelPolicy)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ActiveLabelPolicyByOrg indicates an expected call of ActiveLabelPolicyByOrg.
func (mr *MockQueriesMockRecorder) ActiveLabelPolicyByOrg(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) ActiveLabelPolicyByOrg(ctx, orgID, withOwnerRemoved any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActiveLabelPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).ActiveLabelPolicyByOrg), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActiveLabelPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).ActiveLabelPolicyByOrg), ctx, orgID, withOwnerRemoved)
}
// ActivePrivateSigningKey mocks base method.
func (m *MockQueries) ActivePrivateSigningKey(ctx context.Context, t time.Time) (*query.PrivateKeys, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ActivePrivateSigningKey", ctx, t)
ret0, _ := ret[0].(*query.PrivateKeys)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ActivePrivateSigningKey indicates an expected call of ActivePrivateSigningKey.
func (mr *MockQueriesMockRecorder) ActivePrivateSigningKey(ctx, t any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivePrivateSigningKey", reflect.TypeOf((*MockQueries)(nil).ActivePrivateSigningKey), ctx, t)
}
// CustomTextListByTemplate mocks base method.
func (m *MockQueries) CustomTextListByTemplate(arg0 context.Context, arg1, arg2 string, arg3 bool) (*query.CustomTexts, error) {
func (m *MockQueries) CustomTextListByTemplate(ctx context.Context, aggregateID, template string, withOwnerRemoved bool) (*query.CustomTexts, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CustomTextListByTemplate", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "CustomTextListByTemplate", ctx, aggregateID, template, withOwnerRemoved)
ret0, _ := ret[0].(*query.CustomTexts)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CustomTextListByTemplate indicates an expected call of CustomTextListByTemplate.
func (mr *MockQueriesMockRecorder) CustomTextListByTemplate(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) CustomTextListByTemplate(ctx, aggregateID, template, withOwnerRemoved any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CustomTextListByTemplate", reflect.TypeOf((*MockQueries)(nil).CustomTextListByTemplate), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CustomTextListByTemplate", reflect.TypeOf((*MockQueries)(nil).CustomTextListByTemplate), ctx, aggregateID, template, withOwnerRemoved)
}
// GetActiveSigningWebKey mocks base method.
func (m *MockQueries) GetActiveSigningWebKey(ctx context.Context) (*jose.JSONWebKey, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetActiveSigningWebKey", ctx)
ret0, _ := ret[0].(*jose.JSONWebKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetActiveSigningWebKey indicates an expected call of GetActiveSigningWebKey.
func (mr *MockQueriesMockRecorder) GetActiveSigningWebKey(ctx any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveSigningWebKey", reflect.TypeOf((*MockQueries)(nil).GetActiveSigningWebKey), ctx)
}
// GetDefaultLanguage mocks base method.
func (m *MockQueries) GetDefaultLanguage(arg0 context.Context) language.Tag {
func (m *MockQueries) GetDefaultLanguage(ctx context.Context) language.Tag {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDefaultLanguage", arg0)
ret := m.ctrl.Call(m, "GetDefaultLanguage", ctx)
ret0, _ := ret[0].(language.Tag)
return ret0
}
// GetDefaultLanguage indicates an expected call of GetDefaultLanguage.
func (mr *MockQueriesMockRecorder) GetDefaultLanguage(arg0 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) GetDefaultLanguage(ctx any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultLanguage", reflect.TypeOf((*MockQueries)(nil).GetDefaultLanguage), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultLanguage", reflect.TypeOf((*MockQueries)(nil).GetDefaultLanguage), ctx)
}
// GetInstanceRestrictions mocks base method.
func (m *MockQueries) GetInstanceRestrictions(arg0 context.Context) (query.Restrictions, error) {
func (m *MockQueries) GetInstanceRestrictions(ctx context.Context) (query.Restrictions, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetInstanceRestrictions", arg0)
ret := m.ctrl.Call(m, "GetInstanceRestrictions", ctx)
ret0, _ := ret[0].(query.Restrictions)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetInstanceRestrictions indicates an expected call of GetInstanceRestrictions.
func (mr *MockQueriesMockRecorder) GetInstanceRestrictions(arg0 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) GetInstanceRestrictions(ctx any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceRestrictions", reflect.TypeOf((*MockQueries)(nil).GetInstanceRestrictions), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceRestrictions", reflect.TypeOf((*MockQueries)(nil).GetInstanceRestrictions), ctx)
}
// GetNotifyUserByID mocks base method.
func (m *MockQueries) GetNotifyUserByID(arg0 context.Context, arg1 bool, arg2 string) (*query.NotifyUser, error) {
func (m *MockQueries) GetNotifyUserByID(ctx context.Context, shouldTriggered bool, userID string) (*query.NotifyUser, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetNotifyUserByID", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "GetNotifyUserByID", ctx, shouldTriggered, userID)
ret0, _ := ret[0].(*query.NotifyUser)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetNotifyUserByID indicates an expected call of GetNotifyUserByID.
func (mr *MockQueriesMockRecorder) GetNotifyUserByID(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) GetNotifyUserByID(ctx, shouldTriggered, userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNotifyUserByID", reflect.TypeOf((*MockQueries)(nil).GetNotifyUserByID), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNotifyUserByID", reflect.TypeOf((*MockQueries)(nil).GetNotifyUserByID), ctx, shouldTriggered, userID)
}
// InstanceByID mocks base method.
func (m *MockQueries) InstanceByID(ctx context.Context, id string) (authz.Instance, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InstanceByID", ctx, id)
ret0, _ := ret[0].(authz.Instance)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// InstanceByID indicates an expected call of InstanceByID.
func (mr *MockQueriesMockRecorder) InstanceByID(ctx, id any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceByID", reflect.TypeOf((*MockQueries)(nil).InstanceByID), ctx, id)
}
// MailTemplateByOrg mocks base method.
func (m *MockQueries) MailTemplateByOrg(arg0 context.Context, arg1 string, arg2 bool) (*query.MailTemplate, error) {
func (m *MockQueries) MailTemplateByOrg(ctx context.Context, orgID string, withOwnerRemoved bool) (*query.MailTemplate, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MailTemplateByOrg", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "MailTemplateByOrg", ctx, orgID, withOwnerRemoved)
ret0, _ := ret[0].(*query.MailTemplate)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// MailTemplateByOrg indicates an expected call of MailTemplateByOrg.
func (mr *MockQueriesMockRecorder) MailTemplateByOrg(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) MailTemplateByOrg(ctx, orgID, withOwnerRemoved any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MailTemplateByOrg", reflect.TypeOf((*MockQueries)(nil).MailTemplateByOrg), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MailTemplateByOrg", reflect.TypeOf((*MockQueries)(nil).MailTemplateByOrg), ctx, orgID, withOwnerRemoved)
}
// NotificationPolicyByOrg mocks base method.
func (m *MockQueries) NotificationPolicyByOrg(arg0 context.Context, arg1 bool, arg2 string, arg3 bool) (*query.NotificationPolicy, error) {
func (m *MockQueries) NotificationPolicyByOrg(ctx context.Context, shouldTriggerBulk bool, orgID string, withOwnerRemoved bool) (*query.NotificationPolicy, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NotificationPolicyByOrg", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "NotificationPolicyByOrg", ctx, shouldTriggerBulk, orgID, withOwnerRemoved)
ret0, _ := ret[0].(*query.NotificationPolicy)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NotificationPolicyByOrg indicates an expected call of NotificationPolicyByOrg.
func (mr *MockQueriesMockRecorder) NotificationPolicyByOrg(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) NotificationPolicyByOrg(ctx, shouldTriggerBulk, orgID, withOwnerRemoved any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).NotificationPolicyByOrg), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).NotificationPolicyByOrg), ctx, shouldTriggerBulk, orgID, withOwnerRemoved)
}
// NotificationProviderByIDAndType mocks base method.
func (m *MockQueries) NotificationProviderByIDAndType(arg0 context.Context, arg1 string, arg2 domain.NotificationProviderType) (*query.DebugNotificationProvider, error) {
func (m *MockQueries) NotificationProviderByIDAndType(ctx context.Context, aggID string, providerType domain.NotificationProviderType) (*query.DebugNotificationProvider, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NotificationProviderByIDAndType", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "NotificationProviderByIDAndType", ctx, aggID, providerType)
ret0, _ := ret[0].(*query.DebugNotificationProvider)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// NotificationProviderByIDAndType indicates an expected call of NotificationProviderByIDAndType.
func (mr *MockQueriesMockRecorder) NotificationProviderByIDAndType(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) NotificationProviderByIDAndType(ctx, aggID, providerType any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationProviderByIDAndType", reflect.TypeOf((*MockQueries)(nil).NotificationProviderByIDAndType), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationProviderByIDAndType", reflect.TypeOf((*MockQueries)(nil).NotificationProviderByIDAndType), ctx, aggID, providerType)
}
// SMSProviderConfigActive mocks base method.
func (m *MockQueries) SMSProviderConfigActive(arg0 context.Context, arg1 string) (*query.SMSConfig, error) {
func (m *MockQueries) SMSProviderConfigActive(ctx context.Context, resourceOwner string) (*query.SMSConfig, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SMSProviderConfigActive", arg0, arg1)
ret := m.ctrl.Call(m, "SMSProviderConfigActive", ctx, resourceOwner)
ret0, _ := ret[0].(*query.SMSConfig)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SMSProviderConfigActive indicates an expected call of SMSProviderConfigActive.
func (mr *MockQueriesMockRecorder) SMSProviderConfigActive(arg0, arg1 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) SMSProviderConfigActive(ctx, resourceOwner any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMSProviderConfigActive", reflect.TypeOf((*MockQueries)(nil).SMSProviderConfigActive), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMSProviderConfigActive", reflect.TypeOf((*MockQueries)(nil).SMSProviderConfigActive), ctx, resourceOwner)
}
// SMTPConfigActive mocks base method.
func (m *MockQueries) SMTPConfigActive(arg0 context.Context, arg1 string) (*query.SMTPConfig, error) {
func (m *MockQueries) SMTPConfigActive(ctx context.Context, resourceOwner string) (*query.SMTPConfig, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SMTPConfigActive", arg0, arg1)
ret := m.ctrl.Call(m, "SMTPConfigActive", ctx, resourceOwner)
ret0, _ := ret[0].(*query.SMTPConfig)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SMTPConfigActive indicates an expected call of SMTPConfigActive.
func (mr *MockQueriesMockRecorder) SMTPConfigActive(arg0, arg1 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) SMTPConfigActive(ctx, resourceOwner any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMTPConfigActive", reflect.TypeOf((*MockQueries)(nil).SMTPConfigActive), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMTPConfigActive", reflect.TypeOf((*MockQueries)(nil).SMTPConfigActive), ctx, resourceOwner)
}
// SearchInstanceDomains mocks base method.
func (m *MockQueries) SearchInstanceDomains(arg0 context.Context, arg1 *query.InstanceDomainSearchQueries) (*query.InstanceDomains, error) {
func (m *MockQueries) SearchInstanceDomains(ctx context.Context, queries *query.InstanceDomainSearchQueries) (*query.InstanceDomains, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SearchInstanceDomains", arg0, arg1)
ret := m.ctrl.Call(m, "SearchInstanceDomains", ctx, queries)
ret0, _ := ret[0].(*query.InstanceDomains)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SearchInstanceDomains indicates an expected call of SearchInstanceDomains.
func (mr *MockQueriesMockRecorder) SearchInstanceDomains(arg0, arg1 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) SearchInstanceDomains(ctx, queries any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchInstanceDomains", reflect.TypeOf((*MockQueries)(nil).SearchInstanceDomains), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchInstanceDomains", reflect.TypeOf((*MockQueries)(nil).SearchInstanceDomains), ctx, queries)
}
// SearchMilestones mocks base method.
func (m *MockQueries) SearchMilestones(arg0 context.Context, arg1 []string, arg2 *query.MilestonesSearchQueries) (*query.Milestones, error) {
func (m *MockQueries) SearchMilestones(ctx context.Context, instanceIDs []string, queries *query.MilestonesSearchQueries) (*query.Milestones, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SearchMilestones", arg0, arg1, arg2)
ret := m.ctrl.Call(m, "SearchMilestones", ctx, instanceIDs, queries)
ret0, _ := ret[0].(*query.Milestones)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SearchMilestones indicates an expected call of SearchMilestones.
func (mr *MockQueriesMockRecorder) SearchMilestones(arg0, arg1, arg2 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) SearchMilestones(ctx, instanceIDs, queries any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMilestones", reflect.TypeOf((*MockQueries)(nil).SearchMilestones), arg0, arg1, arg2)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMilestones", reflect.TypeOf((*MockQueries)(nil).SearchMilestones), ctx, instanceIDs, queries)
}
// SessionByID mocks base method.
func (m *MockQueries) SessionByID(arg0 context.Context, arg1 bool, arg2, arg3 string) (*query.Session, error) {
func (m *MockQueries) SessionByID(ctx context.Context, shouldTriggerBulk bool, id, sessionToken string) (*query.Session, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SessionByID", arg0, arg1, arg2, arg3)
ret := m.ctrl.Call(m, "SessionByID", ctx, shouldTriggerBulk, id, sessionToken)
ret0, _ := ret[0].(*query.Session)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SessionByID indicates an expected call of SessionByID.
func (mr *MockQueriesMockRecorder) SessionByID(arg0, arg1, arg2, arg3 any) *gomock.Call {
func (mr *MockQueriesMockRecorder) SessionByID(ctx, shouldTriggerBulk, id, sessionToken any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SessionByID", reflect.TypeOf((*MockQueries)(nil).SessionByID), arg0, arg1, arg2, arg3)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SessionByID", reflect.TypeOf((*MockQueries)(nil).SessionByID), ctx, shouldTriggerBulk, id, sessionToken)
}

View File

@@ -2,9 +2,12 @@ package handlers
import (
"context"
"time"
"github.com/go-jose/go-jose/v4"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
@@ -25,6 +28,9 @@ type Queries interface {
SMTPConfigActive(ctx context.Context, resourceOwner string) (*query.SMTPConfig, error)
GetDefaultLanguage(ctx context.Context) language.Tag
GetInstanceRestrictions(ctx context.Context) (restrictions query.Restrictions, err error)
InstanceByID(ctx context.Context, id string) (instance authz.Instance, err error)
GetActiveSigningWebKey(ctx context.Context) (*jose.JSONWebKey, error)
ActivePrivateSigningKey(ctx context.Context, t time.Time) (keys *query.PrivateKeys, err error)
}
type NotificationQueries struct {

View File

@@ -19,6 +19,7 @@ import (
es_repo_mock "github.com/zitadel/zitadel/internal/eventstore/repository/mock"
"github.com/zitadel/zitadel/internal/notification/channels/email"
channel_mock "github.com/zitadel/zitadel/internal/notification/channels/mock"
"github.com/zitadel/zitadel/internal/notification/channels/set"
"github.com/zitadel/zitadel/internal/notification/channels/sms"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
@@ -1663,6 +1664,10 @@ func (c *channels) Webhook(context.Context, webhook.Config) (*senders.Chain, err
return &c.Chain, nil
}
func (c *channels) SecurityTokenEvent(context.Context, set.Config) (*senders.Chain, error) {
return &c.Chain, nil
}
func expectTemplateQueries(queries *mock.MockQueries, template string) {
queries.EXPECT().GetInstanceRestrictions(gomock.Any()).Return(query.Restrictions{
AllowedLanguages: []language.Tag{language.English},

View File

@@ -0,0 +1,27 @@
package messages
import (
"net/url"
"github.com/zitadel/schema"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/notification/channels"
)
var _ channels.Message = (*Form)(nil)
type Form struct {
Serializable any
TriggeringEvent eventstore.Event
}
func (msg *Form) GetContent() (string, error) {
values := make(url.Values)
err := schema.NewEncoder().Encode(msg.Serializable, values)
return values.Encode(), err
}
func (msg *Form) GetTriggeringEvent() eventstore.Event {
return msg.TriggeringEvent
}

View File

@@ -2,6 +2,7 @@ package notification
import (
"context"
"time"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/crypto"
@@ -17,7 +18,7 @@ var projections []*handler.Handler
func Register(
ctx context.Context,
userHandlerCustomConfig, quotaHandlerCustomConfig, telemetryHandlerCustomConfig projection.CustomConfig,
userHandlerCustomConfig, quotaHandlerCustomConfig, telemetryHandlerCustomConfig, backChannelLogoutHandlerCustomConfig projection.CustomConfig,
telemetryCfg handlers.TelemetryPusherConfig,
externalDomain string,
externalPort uint16,
@@ -25,14 +26,24 @@ func Register(
commands *command.Commands,
queries *query.Queries,
es *eventstore.Eventstore,
otpEmailTmpl string,
fileSystemPath string,
userEncryption, smtpEncryption, smsEncryption crypto.EncryptionAlgorithm,
otpEmailTmpl, fileSystemPath string,
userEncryption, smtpEncryption, smsEncryption, keysEncryptionAlg crypto.EncryptionAlgorithm,
tokenLifetime time.Duration,
) {
q := handlers.NewNotificationQueries(queries, es, externalDomain, externalPort, externalSecure, fileSystemPath, userEncryption, smtpEncryption, smsEncryption)
c := newChannels(q)
projections = append(projections, handlers.NewUserNotifier(ctx, projection.ApplyCustomConfig(userHandlerCustomConfig), commands, q, c, otpEmailTmpl))
projections = append(projections, handlers.NewQuotaNotifier(ctx, projection.ApplyCustomConfig(quotaHandlerCustomConfig), commands, q, c))
projections = append(projections, handlers.NewBackChannelLogoutNotifier(
ctx,
projection.ApplyCustomConfig(backChannelLogoutHandlerCustomConfig),
commands,
q,
es,
keysEncryptionAlg,
c,
tokenLifetime,
))
if telemetryCfg.Enabled {
projections = append(projections, handlers.NewTelemetryPusher(ctx, telemetryCfg, projection.ApplyCustomConfig(telemetryHandlerCustomConfig), commands, q, c))
}

View File

@@ -0,0 +1,49 @@
package senders
import (
"context"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/notification/channels"
"github.com/zitadel/zitadel/internal/notification/channels/fs"
"github.com/zitadel/zitadel/internal/notification/channels/instrumenting"
"github.com/zitadel/zitadel/internal/notification/channels/log"
"github.com/zitadel/zitadel/internal/notification/channels/set"
)
const setSpanName = "security_event_token.NotificationChannel"
func SecurityEventTokenChannels(
ctx context.Context,
setConfig set.Config,
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
getLogProvider func(ctx context.Context) (*log.Config, error),
successMetricName,
failureMetricName string,
) (*Chain, error) {
if err := setConfig.Validate(); err != nil {
return nil, err
}
channels := make([]channels.NotificationChannel, 0, 3)
setChannel, err := set.InitChannel(ctx, setConfig)
logging.WithFields(
"instance", authz.GetInstance(ctx).InstanceID(),
"callurl", setConfig.CallURL,
).OnError(err).Debug("initializing SET channel failed")
if err == nil {
channels = append(
channels,
instrumenting.Wrap(
ctx,
setChannel,
setSpanName,
successMetricName,
failureMetricName,
),
)
}
channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...)
return ChainChannels(channels...), nil
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/i18n"
"github.com/zitadel/zitadel/internal/notification/channels/email"
"github.com/zitadel/zitadel/internal/notification/channels/set"
"github.com/zitadel/zitadel/internal/notification/channels/sms"
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
"github.com/zitadel/zitadel/internal/notification/senders"
@@ -26,6 +27,7 @@ type ChannelChains interface {
Email(context.Context) (*senders.Chain, *email.Config, error)
SMS(context.Context) (*senders.Chain, *sms.Config, error)
Webhook(context.Context, webhook.Config) (*senders.Chain, error)
SecurityTokenEvent(context.Context, set.Config) (*senders.Chain, error)
}
func SendEmail(
@@ -127,3 +129,21 @@ func SendJSON(
)
}
}
func SendSecurityTokenEvent(
ctx context.Context,
setConfig set.Config,
channels ChannelChains,
token any,
triggeringEvent eventstore.Event,
) Notify {
return func(_ string, _ map[string]interface{}, _ string, _ bool) error {
return handleSecurityTokenEvent(
ctx,
setConfig,
channels,
token,
triggeringEvent,
)
}
}

View File

@@ -0,0 +1,27 @@
package types
import (
"context"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/notification/channels/set"
"github.com/zitadel/zitadel/internal/notification/messages"
)
func handleSecurityTokenEvent(
ctx context.Context,
setConfig set.Config,
channels ChannelChains,
token any,
triggeringEvent eventstore.Event,
) error {
message := &messages.Form{
Serializable: token,
TriggeringEvent: triggeringEvent,
}
setChannels, err := channels.SecurityTokenEvent(ctx, setConfig)
if err != nil {
return err
}
return setChannels.HandleMessage(message)
}