mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-05 14:37:45 +00:00
fix: use triggering origin for notification links (#6628)
* take baseurl if saved on event * refactor: make es mocks reusable * Revert "refactor: make es mocks reusable" This reverts commit 434ce12a6acf639514308bc231e76ebb8676b643. * make messages testable * test asset url * fmt * fmt * simplify notification.Start * test url combinations * support init code added * support password changed * support reset pw * support user domain claimed * support add pwless login * support verify phone * Revert "support verify phone" This reverts commit e40503303e2fdda0c85985b3fe3160ce96d43cca. * save trigger origin from ctx * add ready for review check * camel * test email otp * fix variable naming * fix DefaultOTPEmailURLV2 * Revert "fix DefaultOTPEmailURLV2" This reverts commit fa34d4d2a83fbfd8353759c9148af9165a9dd44c. * fix email otp challenged test * fix email otp challenged test * pass origin in login and gateway requests * take origin from header * take x-forwarded if present * Update internal/notification/handlers/queries.go Co-authored-by: Tim Möhlmann <tim+github@zitadel.com> * Update internal/notification/handlers/commands.go Co-authored-by: Tim Möhlmann <tim+github@zitadel.com> * move origin header to ctx if available * generate * cleanup * use forwarded header * support X-Forwarded-* headers * standardize context handling * fix linting --------- Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
parent
0180779d6d
commit
8f6cb47567
@ -101,7 +101,8 @@ Please make sure you cover your changes with tests before marking a Pull Request
|
||||
- [ ] Integration tests against the gRPC server ensure that probable good and bad read and write permissions are tested.
|
||||
- [ ] Integration tests against the gRPC server ensure that the API is easily usable despite eventual consistency.
|
||||
- [ ] Integration tests against the gRPC server ensure that all probable login and registration flows are covered."
|
||||
- [ ] Integration tests ensure that certain commands send expected notifications.
|
||||
- [ ] Integration tests ensure that certain commands emit expected events that trigger notifications.
|
||||
- [ ] Integration tests ensure that certain events trigger expected notifications.
|
||||
|
||||
## Contribute
|
||||
|
||||
|
@ -235,7 +235,6 @@ func startZitadel(config *Config, masterKey string, server chan<- *Server) error
|
||||
commands,
|
||||
queries,
|
||||
eventstoreClient,
|
||||
assets.AssetAPIFromDomain(config.ExternalSecure, config.ExternalPort),
|
||||
config.Login.DefaultOTPEmailURLV2,
|
||||
config.SystemDefaults.Notifications.FileSystemPath,
|
||||
keys.User,
|
||||
@ -311,6 +310,8 @@ func startAPIs(
|
||||
authZRepo,
|
||||
queries,
|
||||
}
|
||||
// always set the origin in the context if available in the http headers, no matter for what protocol
|
||||
router.Use(middleware.OriginHandler)
|
||||
verifier := internal_authz.Start(repo, http_util.BuildHTTP(config.ExternalDomain, config.ExternalPort, config.ExternalSecure), config.SystemAPIUsers)
|
||||
tlsConfig, err := config.TLS.Config()
|
||||
if err != nil {
|
||||
@ -444,7 +445,6 @@ func startAPIs(
|
||||
if err := apis.RegisterService(ctx, oidc_v2.CreateServer(commands, queries, oidcProvider, config.ExternalSecure)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// handle grpc at last to be able to handle the root, because grpc and gateway require a lot of different prefixes
|
||||
apis.RouteGRPC()
|
||||
return nil
|
||||
|
@ -55,12 +55,6 @@ func AssetAPI(externalSecure bool) func(context.Context) string {
|
||||
}
|
||||
}
|
||||
|
||||
func AssetAPIFromDomain(externalSecure bool, externalPort uint16) func(context.Context) string {
|
||||
return func(ctx context.Context) string {
|
||||
return http_util.BuildHTTP(authz.GetInstance(ctx).RequestedDomain(), externalPort, externalSecure) + HandlerPrefix
|
||||
}
|
||||
}
|
||||
|
||||
type Uploader interface {
|
||||
UploadAsset(ctx context.Context, info string, asset *command.AssetUpload, commands *command.Commands) error
|
||||
ObjectName(data authz.CtxData) (string, error)
|
||||
|
@ -133,7 +133,7 @@ func GetAllPermissionsFromCtx(ctx context.Context) []string {
|
||||
func checkOrigin(ctx context.Context, origins []string) error {
|
||||
origin := grpc.GetGatewayHeader(ctx, http_util.Origin)
|
||||
if origin == "" {
|
||||
origin = http_util.OriginFromCtx(ctx)
|
||||
origin = http_util.OriginHeader(ctx)
|
||||
if origin == "" {
|
||||
return nil
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ type key int
|
||||
const (
|
||||
httpHeaders key = iota
|
||||
remoteAddr
|
||||
origin
|
||||
)
|
||||
|
||||
func CopyHeadersToContext(h http.Handler) http.Handler {
|
||||
@ -61,7 +62,7 @@ func HeadersFromCtx(ctx context.Context) (http.Header, bool) {
|
||||
return headers, ok
|
||||
}
|
||||
|
||||
func OriginFromCtx(ctx context.Context) string {
|
||||
func OriginHeader(ctx context.Context) string {
|
||||
headers, ok := ctx.Value(httpHeaders).(http.Header)
|
||||
if !ok {
|
||||
return ""
|
||||
@ -69,6 +70,18 @@ func OriginFromCtx(ctx context.Context) string {
|
||||
return headers.Get(Origin)
|
||||
}
|
||||
|
||||
func ComposedOrigin(ctx context.Context) string {
|
||||
o, ok := ctx.Value(origin).(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func WithComposedOrigin(ctx context.Context, composed string) context.Context {
|
||||
return context.WithValue(ctx, origin, composed)
|
||||
}
|
||||
|
||||
func RemoteIPFromCtx(ctx context.Context) string {
|
||||
ctxHeaders, ok := HeadersFromCtx(ctx)
|
||||
if !ok {
|
||||
|
103
internal/api/http/middleware/origin_interceptor.go
Normal file
103
internal/api/http/middleware/origin_interceptor.go
Normal file
@ -0,0 +1,103 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/muhlemmer/httpforwarded"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
)
|
||||
|
||||
func OriginHandler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
origin := composeOrigin(r)
|
||||
if !http_util.IsOrigin(origin) {
|
||||
logging.Debugf("extracted origin is not valid: %s", origin)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r.WithContext(http_util.WithComposedOrigin(r.Context(), origin)))
|
||||
})
|
||||
}
|
||||
|
||||
func composeOrigin(r *http.Request) string {
|
||||
if origin, err := originFromForwardedHeader(r); err != nil {
|
||||
logging.OnError(err).Debug("failed to build origin from forwarded header, trying x-forwarded-* headers")
|
||||
} else {
|
||||
return origin
|
||||
}
|
||||
if origin, err := originFromXForwardedHeaders(r); err != nil {
|
||||
logging.OnError(err).Debug("failed to build origin from x-forwarded-* headers, using host header")
|
||||
} else {
|
||||
return origin
|
||||
}
|
||||
scheme := "https"
|
||||
if r.TLS == nil {
|
||||
scheme = "http"
|
||||
}
|
||||
return fmt.Sprintf("%s://%s", scheme, r.Host)
|
||||
}
|
||||
|
||||
func originFromForwardedHeader(r *http.Request) (string, error) {
|
||||
fwd, err := httpforwarded.ParseFromRequest(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var fwdProto, fwdHost, fwdPort string
|
||||
if fwdProto = mostRecentValue(fwd, "proto"); fwdProto == "" {
|
||||
return "", fmt.Errorf("no proto in forwarded header")
|
||||
}
|
||||
if fwdHost = mostRecentValue(fwd, "host"); fwdHost == "" {
|
||||
return "", fmt.Errorf("no host in forwarded header")
|
||||
}
|
||||
fwdPort, foundFwdFor := extractPort(mostRecentValue(fwd, "for"))
|
||||
if !foundFwdFor {
|
||||
return "", fmt.Errorf("no for in forwarded header")
|
||||
}
|
||||
o := fmt.Sprintf("%s://%s", fwdProto, fwdHost)
|
||||
if fwdPort != "" {
|
||||
o += ":" + fwdPort
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func originFromXForwardedHeaders(r *http.Request) (string, error) {
|
||||
scheme := r.Header.Get("X-Forwarded-Proto")
|
||||
if scheme == "" {
|
||||
return "", fmt.Errorf("no X-Forwarded-Proto header")
|
||||
}
|
||||
host := r.Header.Get("X-Forwarded-Host")
|
||||
if host == "" {
|
||||
return "", fmt.Errorf("no X-Forwarded-Host header")
|
||||
}
|
||||
return fmt.Sprintf("%s://%s", scheme, host), nil
|
||||
}
|
||||
|
||||
func extractPort(raw string) (string, bool) {
|
||||
if u, ok := parseURL(raw); ok {
|
||||
return u.Port(), ok
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func parseURL(raw string) (*url.URL, bool) {
|
||||
if raw == "" {
|
||||
return nil, false
|
||||
}
|
||||
u, err := url.Parse(raw)
|
||||
return u, err == nil
|
||||
}
|
||||
|
||||
func mostRecentValue(forwarded map[string][]string, key string) string {
|
||||
if forwarded == nil {
|
||||
return ""
|
||||
}
|
||||
values := forwarded[key]
|
||||
if len(values) == 0 {
|
||||
return ""
|
||||
}
|
||||
return values[len(values)-1]
|
||||
}
|
106
internal/notification/channels.go
Normal file
106
internal/notification/channels.go
Normal file
@ -0,0 +1,106 @@
|
||||
package notification
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/handlers"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
"github.com/zitadel/zitadel/internal/notification/types"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
)
|
||||
|
||||
var _ types.ChannelChains = (*channels)(nil)
|
||||
|
||||
type counters struct {
|
||||
success deliveryMetrics
|
||||
failed deliveryMetrics
|
||||
}
|
||||
|
||||
type deliveryMetrics struct {
|
||||
email string
|
||||
sms string
|
||||
json string
|
||||
}
|
||||
|
||||
type channels struct {
|
||||
q *handlers.NotificationQueries
|
||||
counters counters
|
||||
}
|
||||
|
||||
func newChannels(q *handlers.NotificationQueries) *channels {
|
||||
c := &channels{
|
||||
q: q,
|
||||
counters: counters{
|
||||
success: deliveryMetrics{
|
||||
email: "successful_deliveries_email",
|
||||
sms: "successful_deliveries_sms",
|
||||
json: "successful_deliveries_json",
|
||||
},
|
||||
failed: deliveryMetrics{
|
||||
email: "failed_deliveries_email",
|
||||
sms: "failed_deliveries_sms",
|
||||
json: "failed_deliveries_json",
|
||||
},
|
||||
},
|
||||
}
|
||||
registerCounter(c.counters.success.email, "Successfully delivered emails")
|
||||
registerCounter(c.counters.failed.email, "Failed email deliveries")
|
||||
registerCounter(c.counters.success.sms, "Successfully delivered SMS")
|
||||
registerCounter(c.counters.failed.sms, "Failed SMS deliveries")
|
||||
registerCounter(c.counters.success.json, "Successfully delivered JSON messages")
|
||||
registerCounter(c.counters.failed.json, "Failed JSON message deliveries")
|
||||
return c
|
||||
}
|
||||
|
||||
func registerCounter(counter, desc string) {
|
||||
err := metrics.RegisterCounter(counter, desc)
|
||||
logging.WithFields("metric", counter).OnError(err).Panic("unable to register counter")
|
||||
}
|
||||
|
||||
func (c *channels) Email(ctx context.Context) (*senders.Chain, *smtp.Config, error) {
|
||||
smtpCfg, err := c.q.GetSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
chain, err := senders.EmailChannels(
|
||||
ctx,
|
||||
smtpCfg,
|
||||
c.q.GetFileSystemProvider,
|
||||
c.q.GetLogProvider,
|
||||
c.counters.success.email,
|
||||
c.counters.failed.email,
|
||||
)
|
||||
return chain, smtpCfg, err
|
||||
}
|
||||
|
||||
func (c *channels) SMS(ctx context.Context) (*senders.Chain, *twilio.Config, error) {
|
||||
twilioCfg, err := c.q.GetTwilioConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
chain, err := senders.SMSChannels(
|
||||
ctx,
|
||||
twilioCfg,
|
||||
c.q.GetFileSystemProvider,
|
||||
c.q.GetLogProvider,
|
||||
c.counters.success.sms,
|
||||
c.counters.failed.sms,
|
||||
)
|
||||
return chain, twilioCfg, err
|
||||
}
|
||||
|
||||
func (c *channels) Webhook(ctx context.Context, cfg webhook.Config) (*senders.Chain, error) {
|
||||
return senders.WebhookChannels(
|
||||
ctx,
|
||||
cfg,
|
||||
c.q.GetFileSystemProvider,
|
||||
c.q.GetLogProvider,
|
||||
c.counters.success.json,
|
||||
c.counters.failed.json,
|
||||
)
|
||||
}
|
@ -5,8 +5,8 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
channels "github.com/zitadel/zitadel/internal/notification/channels"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
channels "github.com/zitadel/zitadel/internal/notification/channels"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
|
@ -6,6 +6,7 @@ package mock
|
||||
|
||||
import (
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
eventstore "github.com/zitadel/zitadel/internal/eventstore"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
@ -33,11 +34,12 @@ func (m *MockMessage) EXPECT() *MockMessageMockRecorder {
|
||||
}
|
||||
|
||||
// GetContent mocks base method
|
||||
func (m *MockMessage) GetContent() string {
|
||||
func (m *MockMessage) GetContent() (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetContent")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetContent indicates an expected call of GetContent
|
||||
@ -45,3 +47,17 @@ func (mr *MockMessageMockRecorder) GetContent() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetContent", reflect.TypeOf((*MockMessage)(nil).GetContent))
|
||||
}
|
||||
|
||||
// GetTriggeringEvent mocks base method
|
||||
func (m *MockMessage) GetTriggeringEvent() eventstore.Event {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetTriggeringEvent")
|
||||
ret0, _ := ret[0].(eventstore.Event)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetTriggeringEvent indicates an expected call of GetTriggeringEvent
|
||||
func (mr *MockMessageMockRecorder) GetTriggeringEvent() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTriggeringEvent", reflect.TypeOf((*MockMessage)(nil).GetTriggeringEvent))
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/smtp"
|
||||
@ -23,24 +22,18 @@ type Email struct {
|
||||
replyToAddress string
|
||||
}
|
||||
|
||||
func InitChannel(ctx context.Context, getSMTPConfig func(ctx context.Context) (*Config, error)) (*Email, error) {
|
||||
smtpConfig, err := getSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls)
|
||||
func InitChannel(cfg *Config) (*Email, error) {
|
||||
client, err := cfg.SMTP.connectToSMTP(cfg.Tls)
|
||||
if err != nil {
|
||||
logging.New().WithError(err).Error("could not connect to smtp")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logging.New().Debug("successfully initialized smtp email channel")
|
||||
|
||||
return &Email{
|
||||
smtpClient: client,
|
||||
senderName: smtpConfig.FromName,
|
||||
senderAddress: smtpConfig.From,
|
||||
replyToAddress: smtpConfig.ReplyToAddress,
|
||||
senderName: cfg.FromName,
|
||||
senderAddress: cfg.From,
|
||||
replyToAddress: cfg.ReplyToAddress,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
24
internal/notification/handlers/commands.go
Normal file
24
internal/notification/handlers/commands.go
Normal file
@ -0,0 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/repository/milestone"
|
||||
"github.com/zitadel/zitadel/internal/repository/quota"
|
||||
)
|
||||
|
||||
type Commands interface {
|
||||
HumanInitCodeSent(ctx context.Context, orgID, userID string) error
|
||||
HumanEmailVerificationCodeSent(ctx context.Context, orgID, userID string) error
|
||||
PasswordCodeSent(ctx context.Context, orgID, userID string) error
|
||||
HumanOTPSMSCodeSent(ctx context.Context, userID, resourceOwner string) error
|
||||
HumanOTPEmailCodeSent(ctx context.Context, userID, resourceOwner string) error
|
||||
OTPSMSSent(ctx context.Context, sessionID, resourceOwner string) error
|
||||
OTPEmailSent(ctx context.Context, sessionID, resourceOwner string) error
|
||||
UserDomainClaimedSent(ctx context.Context, orgID, userID string) error
|
||||
HumanPasswordlessInitCodeSent(ctx context.Context, userID, resourceOwner, codeID string) error
|
||||
PasswordChangeSent(ctx context.Context, orgID, userID string) error
|
||||
HumanPhoneVerificationCodeSent(ctx context.Context, orgID, userID string) error
|
||||
UsageNotificationSent(ctx context.Context, dueEvent *quota.NotificationDueEvent) error
|
||||
MilestonePushed(ctx context.Context, msType milestone.Type, endpoints []string, primaryDomain string) error
|
||||
}
|
4
internal/notification/handlers/gen_mock.go
Normal file
4
internal/notification/handlers/gen_mock.go
Normal file
@ -0,0 +1,4 @@
|
||||
package handlers
|
||||
|
||||
//go:generate mockgen -package mock -destination ./mock/queries.mock.go github.com/zitadel/zitadel/internal/notification/handlers Queries
|
||||
//go:generate mockgen -package mock -destination ./mock/commands.mock.go github.com/zitadel/zitadel/internal/notification/handlers Commands
|
218
internal/notification/handlers/mock/commands.mock.go
Normal file
218
internal/notification/handlers/mock/commands.mock.go
Normal file
@ -0,0 +1,218 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/internal/notification/handlers (interfaces: Commands)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
milestone "github.com/zitadel/zitadel/internal/repository/milestone"
|
||||
quota "github.com/zitadel/zitadel/internal/repository/quota"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockCommands is a mock of Commands interface
|
||||
type MockCommands struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCommandsMockRecorder
|
||||
}
|
||||
|
||||
// MockCommandsMockRecorder is the mock recorder for MockCommands
|
||||
type MockCommandsMockRecorder struct {
|
||||
mock *MockCommands
|
||||
}
|
||||
|
||||
// NewMockCommands creates a new mock instance
|
||||
func NewMockCommands(ctrl *gomock.Controller) *MockCommands {
|
||||
mock := &MockCommands{ctrl: ctrl}
|
||||
mock.recorder = &MockCommandsMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockCommands) EXPECT() *MockCommandsMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// HumanEmailVerificationCodeSent mocks base method
|
||||
func (m *MockCommands) HumanEmailVerificationCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanEmailVerificationCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanEmailVerificationCodeSent indicates an expected call of HumanEmailVerificationCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanEmailVerificationCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanEmailVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanEmailVerificationCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// HumanInitCodeSent mocks base method
|
||||
func (m *MockCommands) HumanInitCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanInitCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanInitCodeSent indicates an expected call of HumanInitCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanInitCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanInitCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// HumanOTPEmailCodeSent mocks base method
|
||||
func (m *MockCommands) HumanOTPEmailCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanOTPEmailCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanOTPEmailCodeSent indicates an expected call of HumanOTPEmailCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanOTPEmailCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPEmailCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPEmailCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// HumanOTPSMSCodeSent mocks base method
|
||||
func (m *MockCommands) HumanOTPSMSCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanOTPSMSCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanOTPSMSCodeSent indicates an expected call of HumanOTPSMSCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanOTPSMSCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanOTPSMSCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanOTPSMSCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// HumanPasswordlessInitCodeSent mocks base method
|
||||
func (m *MockCommands) HumanPasswordlessInitCodeSent(arg0 context.Context, arg1, arg2, arg3 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanPasswordlessInitCodeSent", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanPasswordlessInitCodeSent indicates an expected call of HumanPasswordlessInitCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanPasswordlessInitCodeSent(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPasswordlessInitCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPasswordlessInitCodeSent), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// HumanPhoneVerificationCodeSent mocks base method
|
||||
func (m *MockCommands) HumanPhoneVerificationCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HumanPhoneVerificationCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HumanPhoneVerificationCodeSent indicates an expected call of HumanPhoneVerificationCodeSent
|
||||
func (mr *MockCommandsMockRecorder) HumanPhoneVerificationCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HumanPhoneVerificationCodeSent", reflect.TypeOf((*MockCommands)(nil).HumanPhoneVerificationCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// MilestonePushed mocks base method
|
||||
func (m *MockCommands) MilestonePushed(arg0 context.Context, arg1 milestone.Type, arg2 []string, arg3 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MilestonePushed", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MilestonePushed indicates an expected call of MilestonePushed
|
||||
func (mr *MockCommandsMockRecorder) MilestonePushed(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MilestonePushed", reflect.TypeOf((*MockCommands)(nil).MilestonePushed), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// OTPEmailSent mocks base method
|
||||
func (m *MockCommands) OTPEmailSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OTPEmailSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// OTPEmailSent indicates an expected call of OTPEmailSent
|
||||
func (mr *MockCommandsMockRecorder) OTPEmailSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPEmailSent", reflect.TypeOf((*MockCommands)(nil).OTPEmailSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// OTPSMSSent mocks base method
|
||||
func (m *MockCommands) OTPSMSSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "OTPSMSSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// OTPSMSSent indicates an expected call of OTPSMSSent
|
||||
func (mr *MockCommandsMockRecorder) OTPSMSSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OTPSMSSent", reflect.TypeOf((*MockCommands)(nil).OTPSMSSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// PasswordChangeSent mocks base method
|
||||
func (m *MockCommands) PasswordChangeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PasswordChangeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PasswordChangeSent indicates an expected call of PasswordChangeSent
|
||||
func (mr *MockCommandsMockRecorder) PasswordChangeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordChangeSent", reflect.TypeOf((*MockCommands)(nil).PasswordChangeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// PasswordCodeSent mocks base method
|
||||
func (m *MockCommands) PasswordCodeSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PasswordCodeSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PasswordCodeSent indicates an expected call of PasswordCodeSent
|
||||
func (mr *MockCommandsMockRecorder) PasswordCodeSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PasswordCodeSent", reflect.TypeOf((*MockCommands)(nil).PasswordCodeSent), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// UsageNotificationSent mocks base method
|
||||
func (m *MockCommands) UsageNotificationSent(arg0 context.Context, arg1 *quota.NotificationDueEvent) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UsageNotificationSent", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UsageNotificationSent indicates an expected call of UsageNotificationSent
|
||||
func (mr *MockCommandsMockRecorder) UsageNotificationSent(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UsageNotificationSent", reflect.TypeOf((*MockCommands)(nil).UsageNotificationSent), arg0, arg1)
|
||||
}
|
||||
|
||||
// UserDomainClaimedSent mocks base method
|
||||
func (m *MockCommands) UserDomainClaimedSent(arg0 context.Context, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserDomainClaimedSent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserDomainClaimedSent indicates an expected call of UserDomainClaimedSent
|
||||
func (mr *MockCommandsMockRecorder) UserDomainClaimedSent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserDomainClaimedSent", reflect.TypeOf((*MockCommands)(nil).UserDomainClaimedSent), arg0, arg1, arg2)
|
||||
}
|
226
internal/notification/handlers/mock/queries.mock.go
Normal file
226
internal/notification/handlers/mock/queries.mock.go
Normal file
@ -0,0 +1,226 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/zitadel/zitadel/internal/notification/handlers (interfaces: Queries)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
domain "github.com/zitadel/zitadel/internal/domain"
|
||||
query "github.com/zitadel/zitadel/internal/query"
|
||||
language "golang.org/x/text/language"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockQueries is a mock of Queries interface
|
||||
type MockQueries struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockQueriesMockRecorder
|
||||
}
|
||||
|
||||
// MockQueriesMockRecorder is the mock recorder for MockQueries
|
||||
type MockQueriesMockRecorder struct {
|
||||
mock *MockQueries
|
||||
}
|
||||
|
||||
// NewMockQueries creates a new mock instance
|
||||
func NewMockQueries(ctrl *gomock.Controller) *MockQueries {
|
||||
mock := &MockQueries{ctrl: ctrl}
|
||||
mock.recorder = &MockQueriesMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockQueries) EXPECT() *MockQueriesMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ActiveLabelPolicyByOrg mocks base method
|
||||
func (m *MockQueries) ActiveLabelPolicyByOrg(arg0 context.Context, arg1 string, arg2 bool) (*query.LabelPolicy, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ActiveLabelPolicyByOrg", arg0, arg1, arg2)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActiveLabelPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).ActiveLabelPolicyByOrg), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// CustomTextListByTemplate mocks base method
|
||||
func (m *MockQueries) CustomTextListByTemplate(arg0 context.Context, arg1, arg2 string, arg3 bool) (*query.CustomTexts, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CustomTextListByTemplate", arg0, arg1, arg2, arg3)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CustomTextListByTemplate", reflect.TypeOf((*MockQueries)(nil).CustomTextListByTemplate), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// GetDefaultLanguage mocks base method
|
||||
func (m *MockQueries) GetDefaultLanguage(arg0 context.Context) language.Tag {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetDefaultLanguage", arg0)
|
||||
ret0, _ := ret[0].(language.Tag)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetDefaultLanguage indicates an expected call of GetDefaultLanguage
|
||||
func (mr *MockQueriesMockRecorder) GetDefaultLanguage(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultLanguage", reflect.TypeOf((*MockQueries)(nil).GetDefaultLanguage), arg0)
|
||||
}
|
||||
|
||||
// GetNotifyUserByID mocks base method
|
||||
func (m *MockQueries) GetNotifyUserByID(arg0 context.Context, arg1 bool, arg2 string, arg3 bool, arg4 ...query.SearchQuery) (*query.NotifyUser, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1, arg2, arg3}
|
||||
for _, a := range arg4 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GetNotifyUserByID", varargs...)
|
||||
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, arg3 interface{}, arg4 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1, arg2, arg3}, arg4...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNotifyUserByID", reflect.TypeOf((*MockQueries)(nil).GetNotifyUserByID), varargs...)
|
||||
}
|
||||
|
||||
// MailTemplateByOrg mocks base method
|
||||
func (m *MockQueries) MailTemplateByOrg(arg0 context.Context, arg1 string, arg2 bool) (*query.MailTemplate, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MailTemplateByOrg", arg0, arg1, arg2)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MailTemplateByOrg", reflect.TypeOf((*MockQueries)(nil).MailTemplateByOrg), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// NotificationPolicyByOrg mocks base method
|
||||
func (m *MockQueries) NotificationPolicyByOrg(arg0 context.Context, arg1 bool, arg2 string, arg3 bool) (*query.NotificationPolicy, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NotificationPolicyByOrg", arg0, arg1, arg2, arg3)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationPolicyByOrg", reflect.TypeOf((*MockQueries)(nil).NotificationPolicyByOrg), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// NotificationProviderByIDAndType mocks base method
|
||||
func (m *MockQueries) NotificationProviderByIDAndType(arg0 context.Context, arg1 string, arg2 domain.NotificationProviderType) (*query.DebugNotificationProvider, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NotificationProviderByIDAndType", arg0, arg1, arg2)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NotificationProviderByIDAndType", reflect.TypeOf((*MockQueries)(nil).NotificationProviderByIDAndType), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// SMSProviderConfig mocks base method
|
||||
func (m *MockQueries) SMSProviderConfig(arg0 context.Context, arg1 ...query.SearchQuery) (*query.SMSConfig, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0}
|
||||
for _, a := range arg1 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "SMSProviderConfig", varargs...)
|
||||
ret0, _ := ret[0].(*query.SMSConfig)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SMSProviderConfig indicates an expected call of SMSProviderConfig
|
||||
func (mr *MockQueriesMockRecorder) SMSProviderConfig(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0}, arg1...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMSProviderConfig", reflect.TypeOf((*MockQueries)(nil).SMSProviderConfig), varargs...)
|
||||
}
|
||||
|
||||
// SMTPConfigByAggregateID mocks base method
|
||||
func (m *MockQueries) SMTPConfigByAggregateID(arg0 context.Context, arg1 string) (*query.SMTPConfig, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SMTPConfigByAggregateID", arg0, arg1)
|
||||
ret0, _ := ret[0].(*query.SMTPConfig)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SMTPConfigByAggregateID indicates an expected call of SMTPConfigByAggregateID
|
||||
func (mr *MockQueriesMockRecorder) SMTPConfigByAggregateID(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SMTPConfigByAggregateID", reflect.TypeOf((*MockQueries)(nil).SMTPConfigByAggregateID), arg0, arg1)
|
||||
}
|
||||
|
||||
// SearchInstanceDomains mocks base method
|
||||
func (m *MockQueries) SearchInstanceDomains(arg0 context.Context, arg1 *query.InstanceDomainSearchQueries) (*query.InstanceDomains, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SearchInstanceDomains", arg0, arg1)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchInstanceDomains", reflect.TypeOf((*MockQueries)(nil).SearchInstanceDomains), arg0, arg1)
|
||||
}
|
||||
|
||||
// SearchMilestones mocks base method
|
||||
func (m *MockQueries) SearchMilestones(arg0 context.Context, arg1 []string, arg2 *query.MilestonesSearchQueries) (*query.Milestones, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SearchMilestones", arg0, arg1, arg2)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchMilestones", reflect.TypeOf((*MockQueries)(nil).SearchMilestones), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// SessionByID mocks base method
|
||||
func (m *MockQueries) SessionByID(arg0 context.Context, arg1 bool, arg2, arg3 string) (*query.Session, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SessionByID", arg0, arg1, arg2, arg3)
|
||||
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 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SessionByID", reflect.TypeOf((*MockQueries)(nil).SessionByID), arg0, arg1, arg2, arg3)
|
||||
}
|
@ -2,27 +2,56 @@ package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (n *NotificationQueries) Origin(ctx context.Context) (context.Context, string, error) {
|
||||
type OriginEvent interface {
|
||||
eventstore.Event
|
||||
TriggerOrigin() string
|
||||
}
|
||||
|
||||
func (n *NotificationQueries) Origin(ctx context.Context, e eventstore.Event) (context.Context, error) {
|
||||
originEvent, ok := e.(OriginEvent)
|
||||
if !ok {
|
||||
return ctx, errors.ThrowInternal(fmt.Errorf("event of type %T doesn't implement OriginEvent", e), "NOTIF-3m9fs", "Errors.Internal")
|
||||
}
|
||||
origin := originEvent.TriggerOrigin()
|
||||
if origin != "" {
|
||||
originURL, err := url.Parse(origin)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
return enrichCtx(ctx, originURL.Hostname(), origin), nil
|
||||
}
|
||||
primary, err := query.NewInstanceDomainPrimarySearchQuery(true)
|
||||
if err != nil {
|
||||
return ctx, "", err
|
||||
return ctx, err
|
||||
}
|
||||
domains, err := n.SearchInstanceDomains(ctx, &query.InstanceDomainSearchQueries{
|
||||
Queries: []query.SearchQuery{primary},
|
||||
})
|
||||
if err != nil {
|
||||
return ctx, "", err
|
||||
return ctx, err
|
||||
}
|
||||
if len(domains.Domains) < 1 {
|
||||
return ctx, "", errors.ThrowInternal(nil, "NOTIF-Ef3r1", "Errors.Notification.NoDomain")
|
||||
return ctx, errors.ThrowInternal(nil, "NOTIF-Ef3r1", "Errors.Notification.NoDomain")
|
||||
}
|
||||
ctx = authz.WithRequestedDomain(ctx, domains.Domains[0].Domain)
|
||||
return ctx, http_utils.BuildHTTP(domains.Domains[0].Domain, n.externalPort, n.externalSecure), nil
|
||||
return enrichCtx(
|
||||
ctx,
|
||||
domains.Domains[0].Domain,
|
||||
http_utils.BuildHTTP(domains.Domains[0].Domain, n.externalPort, n.externalSecure),
|
||||
), nil
|
||||
}
|
||||
|
||||
func enrichCtx(ctx context.Context, host, origin string) context.Context {
|
||||
ctx = authz.WithRequestedDomain(ctx, host)
|
||||
ctx = http_utils.WithComposedOrigin(ctx, origin)
|
||||
return ctx
|
||||
}
|
||||
|
@ -1,16 +1,34 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
_ "github.com/zitadel/zitadel/internal/notification/statik"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
ActiveLabelPolicyByOrg(ctx context.Context, orgID string, withOwnerRemoved bool) (*query.LabelPolicy, error)
|
||||
MailTemplateByOrg(ctx context.Context, orgID string, withOwnerRemoved bool) (*query.MailTemplate, error)
|
||||
GetNotifyUserByID(ctx context.Context, shouldTriggered bool, userID string, withOwnerRemoved bool, queries ...query.SearchQuery) (*query.NotifyUser, error)
|
||||
CustomTextListByTemplate(ctx context.Context, aggregateID, template string, withOwnerRemoved bool) (*query.CustomTexts, error)
|
||||
SearchInstanceDomains(ctx context.Context, queries *query.InstanceDomainSearchQueries) (*query.InstanceDomains, error)
|
||||
SessionByID(ctx context.Context, shouldTriggerBulk bool, id, sessionToken string) (*query.Session, error)
|
||||
NotificationPolicyByOrg(ctx context.Context, shouldTriggerBulk bool, orgID string, withOwnerRemoved bool) (*query.NotificationPolicy, error)
|
||||
SearchMilestones(ctx context.Context, instanceIDs []string, queries *query.MilestonesSearchQueries) (*query.Milestones, error)
|
||||
NotificationProviderByIDAndType(ctx context.Context, aggID string, providerType domain.NotificationProviderType) (*query.DebugNotificationProvider, error)
|
||||
SMSProviderConfig(ctx context.Context, queries ...query.SearchQuery) (*query.SMSConfig, error)
|
||||
SMTPConfigByAggregateID(ctx context.Context, aggregateID string) (*query.SMTPConfig, error)
|
||||
GetDefaultLanguage(ctx context.Context) language.Tag
|
||||
}
|
||||
|
||||
type NotificationQueries struct {
|
||||
*query.Queries
|
||||
Queries
|
||||
es *eventstore.Eventstore
|
||||
externalDomain string
|
||||
externalPort uint16
|
||||
@ -23,7 +41,7 @@ type NotificationQueries struct {
|
||||
}
|
||||
|
||||
func NewNotificationQueries(
|
||||
baseQueries *query.Queries,
|
||||
baseQueries Queries,
|
||||
es *eventstore.Eventstore,
|
||||
externalDomain string,
|
||||
externalPort uint16,
|
||||
|
@ -22,10 +22,9 @@ const (
|
||||
|
||||
type quotaNotifier struct {
|
||||
crdb.StatementHandler
|
||||
commands *command.Commands
|
||||
queries *NotificationQueries
|
||||
metricSuccessfulDeliveriesJSON string
|
||||
metricFailedDeliveriesJSON string
|
||||
commands *command.Commands
|
||||
queries *NotificationQueries
|
||||
channels types.ChannelChains
|
||||
}
|
||||
|
||||
func NewQuotaNotifier(
|
||||
@ -33,8 +32,7 @@ func NewQuotaNotifier(
|
||||
config crdb.StatementHandlerConfig,
|
||||
commands *command.Commands,
|
||||
queries *NotificationQueries,
|
||||
metricSuccessfulDeliveriesJSON,
|
||||
metricFailedDeliveriesJSON string,
|
||||
channels types.ChannelChains,
|
||||
) *quotaNotifier {
|
||||
p := new(quotaNotifier)
|
||||
config.ProjectionName = QuotaNotificationsProjectionTable
|
||||
@ -42,8 +40,7 @@ func NewQuotaNotifier(
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
p.commands = commands
|
||||
p.queries = queries
|
||||
p.metricSuccessfulDeliveriesJSON = metricSuccessfulDeliveriesJSON
|
||||
p.metricFailedDeliveriesJSON = metricFailedDeliveriesJSON
|
||||
p.channels = channels
|
||||
projection.NotificationsQuotaProjection = p
|
||||
return p
|
||||
}
|
||||
@ -75,19 +72,7 @@ func (u *quotaNotifier) reduceNotificationDue(event eventstore.Event) (*handler.
|
||||
if alreadyHandled {
|
||||
return crdb.NewNoOpStatement(e), nil
|
||||
}
|
||||
err = types.SendJSON(
|
||||
ctx,
|
||||
webhook.Config{
|
||||
CallURL: e.CallURL,
|
||||
Method: http.MethodPost,
|
||||
},
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
e,
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesJSON,
|
||||
u.metricFailedDeliveriesJSON,
|
||||
).WithoutTemplate()
|
||||
err = types.SendJSON(ctx, webhook.Config{CallURL: e.CallURL, Method: http.MethodPost}, u.channels, e, e).WithoutTemplate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -38,11 +38,10 @@ type TelemetryPusherConfig struct {
|
||||
|
||||
type telemetryPusher struct {
|
||||
crdb.StatementHandler
|
||||
cfg TelemetryPusherConfig
|
||||
commands *command.Commands
|
||||
queries *NotificationQueries
|
||||
metricSuccessfulDeliveriesJSON string
|
||||
metricFailedDeliveriesJSON string
|
||||
cfg TelemetryPusherConfig
|
||||
commands *command.Commands
|
||||
queries *NotificationQueries
|
||||
channels types.ChannelChains
|
||||
}
|
||||
|
||||
func NewTelemetryPusher(
|
||||
@ -51,8 +50,7 @@ func NewTelemetryPusher(
|
||||
handlerCfg crdb.StatementHandlerConfig,
|
||||
commands *command.Commands,
|
||||
queries *NotificationQueries,
|
||||
metricSuccessfulDeliveriesJSON,
|
||||
metricFailedDeliveriesJSON string,
|
||||
channels types.ChannelChains,
|
||||
) *telemetryPusher {
|
||||
p := new(telemetryPusher)
|
||||
handlerCfg.ProjectionName = TelemetryProjectionTable
|
||||
@ -62,8 +60,7 @@ func NewTelemetryPusher(
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, handlerCfg)
|
||||
p.commands = commands
|
||||
p.queries = queries
|
||||
p.metricSuccessfulDeliveriesJSON = metricSuccessfulDeliveriesJSON
|
||||
p.metricFailedDeliveriesJSON = metricFailedDeliveriesJSON
|
||||
p.channels = channels
|
||||
projection.TelemetryPusherProjection = p
|
||||
return p
|
||||
}
|
||||
@ -132,8 +129,7 @@ func (t *telemetryPusher) pushMilestone(ctx context.Context, event *pseudo.Sched
|
||||
Method: http.MethodPost,
|
||||
Headers: t.cfg.Headers,
|
||||
},
|
||||
t.queries.GetFileSystemProvider,
|
||||
t.queries.GetLogProvider,
|
||||
t.channels,
|
||||
&struct {
|
||||
InstanceID string `json:"instanceId"`
|
||||
ExternalDomain string `json:"externalDomain"`
|
||||
@ -148,8 +144,6 @@ func (t *telemetryPusher) pushMilestone(ctx context.Context, event *pseudo.Sched
|
||||
ReachedDate: ms.ReachedDate,
|
||||
},
|
||||
event,
|
||||
t.metricSuccessfulDeliveriesJSON,
|
||||
t.metricFailedDeliveriesJSON,
|
||||
).WithoutTemplate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -5,9 +5,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@ -27,27 +26,19 @@ const (
|
||||
|
||||
type userNotifier struct {
|
||||
crdb.StatementHandler
|
||||
commands *command.Commands
|
||||
commands Commands
|
||||
queries *NotificationQueries
|
||||
assetsPrefix func(context.Context) string
|
||||
channels types.ChannelChains
|
||||
otpEmailTmpl string
|
||||
metricSuccessfulDeliveriesEmail,
|
||||
metricFailedDeliveriesEmail,
|
||||
metricSuccessfulDeliveriesSMS,
|
||||
metricFailedDeliveriesSMS string
|
||||
}
|
||||
|
||||
func NewUserNotifier(
|
||||
ctx context.Context,
|
||||
config crdb.StatementHandlerConfig,
|
||||
commands *command.Commands,
|
||||
commands Commands,
|
||||
queries *NotificationQueries,
|
||||
assetsPrefix func(context.Context) string,
|
||||
channels types.ChannelChains,
|
||||
otpEmailTmpl string,
|
||||
metricSuccessfulDeliveriesEmail,
|
||||
metricFailedDeliveriesEmail,
|
||||
metricSuccessfulDeliveriesSMS,
|
||||
metricFailedDeliveriesSMS string,
|
||||
) *userNotifier {
|
||||
p := new(userNotifier)
|
||||
config.ProjectionName = UserNotificationsProjectionTable
|
||||
@ -55,12 +46,8 @@ func NewUserNotifier(
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
p.commands = commands
|
||||
p.queries = queries
|
||||
p.assetsPrefix = assetsPrefix
|
||||
p.channels = channels
|
||||
p.otpEmailTmpl = otpEmailTmpl
|
||||
p.metricSuccessfulDeliveriesEmail = metricSuccessfulDeliveriesEmail
|
||||
p.metricFailedDeliveriesEmail = metricFailedDeliveriesEmail
|
||||
p.metricSuccessfulDeliveriesSMS = metricSuccessfulDeliveriesSMS
|
||||
p.metricFailedDeliveriesSMS = metricFailedDeliveriesSMS
|
||||
projection.NotificationsProjection = p
|
||||
return p
|
||||
}
|
||||
@ -177,25 +164,12 @@ func (u *userNotifier) reduceInitCodeAdded(event eventstore.Event) (*handler.Sta
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
).SendUserInitCode(notifyUser, origin, code)
|
||||
err = types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e).
|
||||
SendUserInitCode(ctx, notifyUser, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -247,25 +221,12 @@ func (u *userNotifier) reduceEmailCodeAdded(event eventstore.Event) (*handler.St
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
).SendEmailVerificationCode(notifyUser, origin, code, e.URLTemplate)
|
||||
err = types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e).
|
||||
SendEmailVerificationCode(ctx, notifyUser, code, e.URLTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -316,41 +277,15 @@ func (u *userNotifier) reducePasswordCodeAdded(event eventstore.Event) (*handler
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
notify := types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
)
|
||||
notify := types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e)
|
||||
if e.NotificationType == domain.NotificationTypeSms {
|
||||
notify = types.SendSMSTwilio(
|
||||
ctx,
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetTwilioConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesSMS,
|
||||
u.metricFailedDeliveriesSMS,
|
||||
)
|
||||
notify = types.SendSMSTwilio(ctx, u.channels, translator, notifyUser, colors, e)
|
||||
}
|
||||
err = notify.SendPasswordCode(notifyUser, origin, code, e.URLTemplate)
|
||||
err = notify.SendPasswordCode(ctx, notifyUser, code, e.URLTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -437,25 +372,12 @@ func (u *userNotifier) reduceOTPSMS(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
notify := types.SendSMSTwilio(
|
||||
ctx,
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetTwilioConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
event,
|
||||
u.metricSuccessfulDeliveriesSMS,
|
||||
u.metricFailedDeliveriesSMS,
|
||||
)
|
||||
err = notify.SendOTPSMSCode(authz.GetInstance(ctx).RequestedDomain(), origin, plainCode, expiry)
|
||||
notify := types.SendSMSTwilio(ctx, u.channels, translator, notifyUser, colors, event)
|
||||
err = notify.SendOTPSMSCode(ctx, plainCode, expiry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -568,30 +490,16 @@ func (u *userNotifier) reduceOTPEmail(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
url, err := urlTmpl(plainCode, origin, notifyUser)
|
||||
url, err := urlTmpl(plainCode, http_util.ComposedOrigin(ctx), notifyUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
notify := types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
event,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
)
|
||||
err = notify.SendOTPEmailCode(notifyUser, url, authz.GetInstance(ctx).RequestedDomain(), origin, plainCode, expiry)
|
||||
notify := types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, event)
|
||||
err = notify.SendOTPEmailCode(ctx, url, plainCode, expiry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -634,25 +542,12 @@ func (u *userNotifier) reduceDomainClaimed(event eventstore.Event) (*handler.Sta
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
).SendDomainClaimed(notifyUser, origin, e.UserName)
|
||||
err = types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e).
|
||||
SendDomainClaimed(ctx, notifyUser, e.UserName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -701,25 +596,12 @@ func (u *userNotifier) reducePasswordlessCodeRequested(event eventstore.Event) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
).SendPasswordlessRegistrationLink(notifyUser, origin, code, e.ID, e.URLTemplate)
|
||||
err = types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e).
|
||||
SendPasswordlessRegistrationLink(ctx, notifyUser, code, e.ID, e.URLTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -771,25 +653,12 @@ func (u *userNotifier) reducePasswordChanged(event eventstore.Event) (*handler.S
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendEmail(
|
||||
ctx,
|
||||
string(template.Template),
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetSMTPConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesEmail,
|
||||
u.metricFailedDeliveriesEmail,
|
||||
).SendPasswordChange(notifyUser, origin)
|
||||
err = types.SendEmail(ctx, u.channels, string(template.Template), translator, notifyUser, colors, e).
|
||||
SendPasswordChange(ctx, notifyUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -836,24 +705,12 @@ func (u *userNotifier) reducePhoneCodeAdded(event eventstore.Event) (*handler.St
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, origin, err := u.queries.Origin(ctx)
|
||||
ctx, err = u.queries.Origin(ctx, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = types.SendSMSTwilio(
|
||||
ctx,
|
||||
translator,
|
||||
notifyUser,
|
||||
u.queries.GetTwilioConfig,
|
||||
u.queries.GetFileSystemProvider,
|
||||
u.queries.GetLogProvider,
|
||||
colors,
|
||||
u.assetsPrefix(ctx),
|
||||
e,
|
||||
u.metricSuccessfulDeliveriesSMS,
|
||||
u.metricFailedDeliveriesSMS,
|
||||
).SendPhoneVerificationCode(notifyUser, origin, code, authz.GetInstance(ctx).RequestedDomain())
|
||||
err = types.SendSMSTwilio(ctx, u.channels, translator, notifyUser, colors, e).
|
||||
SendPhoneVerificationCode(ctx, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
1361
internal/notification/handlers/user_notifier_test.go
Normal file
1361
internal/notification/handlers/user_notifier_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,16 +13,6 @@ import (
|
||||
_ "github.com/zitadel/zitadel/internal/notification/statik"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
metricSuccessfulDeliveriesEmail = "successful_deliveries_email"
|
||||
metricFailedDeliveriesEmail = "failed_deliveries_email"
|
||||
metricSuccessfulDeliveriesSMS = "successful_deliveries_sms"
|
||||
metricFailedDeliveriesSMS = "failed_deliveries_sms"
|
||||
metricSuccessfulDeliveriesJSON = "successful_deliveries_json"
|
||||
metricFailedDeliveriesJSON = "failed_deliveries_json"
|
||||
)
|
||||
|
||||
func Start(
|
||||
@ -35,55 +25,17 @@ func Start(
|
||||
commands *command.Commands,
|
||||
queries *query.Queries,
|
||||
es *eventstore.Eventstore,
|
||||
assetsPrefix func(context.Context) string,
|
||||
otpEmailTmpl string,
|
||||
fileSystemPath string,
|
||||
userEncryption, smtpEncryption, smsEncryption crypto.EncryptionAlgorithm,
|
||||
) {
|
||||
statikFS, err := statik_fs.NewWithNamespace("notification")
|
||||
logging.OnError(err).Panic("unable to start listener")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesEmail, "Successfully delivered emails")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesEmail).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesEmail, "Failed email deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesEmail).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesSMS, "Successfully delivered SMS")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesSMS).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesSMS, "Failed SMS deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesSMS).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricSuccessfulDeliveriesJSON, "Successfully delivered JSON messages")
|
||||
logging.WithFields("metric", metricSuccessfulDeliveriesJSON).OnError(err).Panic("unable to register counter")
|
||||
err = metrics.RegisterCounter(metricFailedDeliveriesJSON, "Failed JSON message deliveries")
|
||||
logging.WithFields("metric", metricFailedDeliveriesJSON).OnError(err).Panic("unable to register counter")
|
||||
q := handlers.NewNotificationQueries(queries, es, externalDomain, externalPort, externalSecure, fileSystemPath, userEncryption, smtpEncryption, smsEncryption, statikFS)
|
||||
handlers.NewUserNotifier(
|
||||
ctx,
|
||||
projection.ApplyCustomConfig(userHandlerCustomConfig),
|
||||
commands,
|
||||
q,
|
||||
assetsPrefix,
|
||||
otpEmailTmpl,
|
||||
metricSuccessfulDeliveriesEmail,
|
||||
metricFailedDeliveriesEmail,
|
||||
metricSuccessfulDeliveriesSMS,
|
||||
metricFailedDeliveriesSMS,
|
||||
).Start()
|
||||
handlers.NewQuotaNotifier(
|
||||
ctx,
|
||||
projection.ApplyCustomConfig(quotaHandlerCustomConfig),
|
||||
commands,
|
||||
q,
|
||||
metricSuccessfulDeliveriesJSON,
|
||||
metricFailedDeliveriesJSON,
|
||||
).Start()
|
||||
c := newChannels(q)
|
||||
handlers.NewUserNotifier(ctx, projection.ApplyCustomConfig(userHandlerCustomConfig), commands, q, c, otpEmailTmpl).Start()
|
||||
handlers.NewQuotaNotifier(ctx, projection.ApplyCustomConfig(quotaHandlerCustomConfig), commands, q, c).Start()
|
||||
if telemetryCfg.Enabled {
|
||||
handlers.NewTelemetryPusher(
|
||||
ctx,
|
||||
telemetryCfg,
|
||||
projection.ApplyCustomConfig(telemetryHandlerCustomConfig),
|
||||
commands,
|
||||
q,
|
||||
metricSuccessfulDeliveriesJSON,
|
||||
metricFailedDeliveriesJSON,
|
||||
).Start()
|
||||
handlers.NewTelemetryPusher(ctx, telemetryCfg, projection.ApplyCustomConfig(telemetryHandlerCustomConfig), commands, q, c).Start()
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ type Chain struct {
|
||||
channels []channels.NotificationChannel
|
||||
}
|
||||
|
||||
func chainChannels(channel ...channels.NotificationChannel) *Chain {
|
||||
func ChainChannels(channel ...channels.NotificationChannel) *Chain {
|
||||
return &Chain{channels: channel}
|
||||
}
|
||||
|
||||
// HandleMessage returns a non nil error from a provider immediately if any occurs
|
||||
// messages are sent to channels in the same order they were provided to chainChannels()
|
||||
// messages are sent to channels in the same order they were provided to ChainChannels()
|
||||
func (c *Chain) HandleMessage(message channels.Message) error {
|
||||
for i := range c.channels {
|
||||
if err := c.channels[i].HandleMessage(message); err != nil {
|
||||
|
@ -17,14 +17,14 @@ const smtpSpanName = "smtp.NotificationChannel"
|
||||
|
||||
func EmailChannels(
|
||||
ctx context.Context,
|
||||
emailConfig func(ctx context.Context) (*smtp.Config, error),
|
||||
emailConfig *smtp.Config,
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) (chain *Chain, err error) {
|
||||
channels := make([]channels.NotificationChannel, 0, 3)
|
||||
p, err := smtp.InitChannel(ctx, emailConfig)
|
||||
p, err := smtp.InitChannel(emailConfig)
|
||||
logging.WithFields(
|
||||
"instance", authz.GetInstance(ctx).InstanceID(),
|
||||
).OnError(err).Debug("initializing SMTP channel failed")
|
||||
@ -41,5 +41,5 @@ func EmailChannels(
|
||||
)
|
||||
}
|
||||
channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...)
|
||||
return chainChannels(channels...), nil
|
||||
return ChainChannels(channels...), nil
|
||||
}
|
||||
|
@ -34,5 +34,5 @@ func SMSChannels(
|
||||
)
|
||||
}
|
||||
channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...)
|
||||
return chainChannels(channels...), nil
|
||||
return ChainChannels(channels...), nil
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
|
||||
const webhookSpanName = "webhook.NotificationChannel"
|
||||
|
||||
func JSONChannels(
|
||||
func WebhookChannels(
|
||||
ctx context.Context,
|
||||
webhookConfig webhook.Config,
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
@ -45,5 +45,5 @@ func JSONChannels(
|
||||
)
|
||||
}
|
||||
channels = append(channels, debugChannels(ctx, getFileSystemProvider, getLogProvider)...)
|
||||
return chainChannels(channels...), nil
|
||||
return ChainChannels(channels...), nil
|
||||
}
|
@ -1,15 +1,17 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendDomainClaimed(user *query.NotifyUser, origin, username string) error {
|
||||
url := login.LoginLink(origin, user.ResourceOwner)
|
||||
func (notify Notify) SendDomainClaimed(ctx context.Context, user *query.NotifyUser, username string) error {
|
||||
url := login.LoginLink(http_utils.ComposedOrigin(ctx), user.ResourceOwner)
|
||||
index := strings.LastIndex(user.LastEmail, "@")
|
||||
args := make(map[string]interface{})
|
||||
args["TempUsername"] = username
|
||||
|
@ -1,17 +1,19 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendEmailVerificationCode(user *query.NotifyUser, origin, code string, urlTmpl string) error {
|
||||
func (notify Notify) SendEmailVerificationCode(ctx context.Context, user *query.NotifyUser, code string, urlTmpl string) error {
|
||||
var url string
|
||||
if urlTmpl == "" {
|
||||
url = login.MailVerificationLink(origin, user.ID, code, user.ResourceOwner)
|
||||
url = login.MailVerificationLink(http_utils.ComposedOrigin(ctx), user.ID, code, user.ResourceOwner)
|
||||
} else {
|
||||
var buf strings.Builder
|
||||
if err := domain.RenderConfirmURLTemplate(&buf, urlTmpl, user.ID, code, user.ResourceOwner); err != nil {
|
||||
|
@ -1,11 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@ -78,7 +80,7 @@ func TestNotify_SendEmailVerificationCode(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, notify := mockNotify()
|
||||
err := notify.SendEmailVerificationCode(tt.args.user, tt.args.origin, tt.args.code, tt.args.urlTmpl)
|
||||
err := notify.SendEmailVerificationCode(http_utils.WithComposedOrigin(context.Background(), tt.args.origin), tt.args.user, tt.args.code, tt.args.urlTmpl)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
|
@ -1,13 +1,16 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendUserInitCode(user *query.NotifyUser, origin, code string) error {
|
||||
url := login.InitUserLink(origin, user.ID, user.PreferredLoginName, code, user.ResourceOwner, user.PasswordSet)
|
||||
func (notify Notify) SendUserInitCode(ctx context.Context, user *query.NotifyUser, code string) error {
|
||||
url := login.InitUserLink(http_utils.ComposedOrigin(ctx), user.ID, user.PreferredLoginName, code, user.ResourceOwner, user.PasswordSet)
|
||||
args := make(map[string]interface{})
|
||||
args["Code"] = code
|
||||
return notify(url, args, domain.InitCodeMessageType, true)
|
||||
|
@ -1,40 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/fs"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/log"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/messages"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
)
|
||||
|
||||
func handleJSON(
|
||||
ctx context.Context,
|
||||
webhookConfig webhook.Config,
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
serializable interface{},
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) error {
|
||||
message := &messages.JSON{
|
||||
Serializable: serializable,
|
||||
TriggeringEvent: triggeringEvent,
|
||||
}
|
||||
channelChain, err := senders.JSONChannels(
|
||||
ctx,
|
||||
webhookConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return channelChain.HandleMessage(message)
|
||||
}
|
@ -5,11 +5,10 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/i18n"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/fs"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/log"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
"github.com/zitadel/zitadel/internal/notification/templates"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
@ -21,19 +20,20 @@ type Notify func(
|
||||
allowUnverifiedNotificationChannel bool,
|
||||
) error
|
||||
|
||||
type ChannelChains interface {
|
||||
Email(context.Context) (*senders.Chain, *smtp.Config, error)
|
||||
SMS(context.Context) (*senders.Chain, *twilio.Config, error)
|
||||
Webhook(context.Context, webhook.Config) (*senders.Chain, error)
|
||||
}
|
||||
|
||||
func SendEmail(
|
||||
ctx context.Context,
|
||||
channels ChannelChains,
|
||||
mailhtml string,
|
||||
translator *i18n.Translator,
|
||||
user *query.NotifyUser,
|
||||
emailConfig func(ctx context.Context) (*smtp.Config, error),
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
colors *query.LabelPolicy,
|
||||
assetsPrefix string,
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) Notify {
|
||||
return func(
|
||||
url string,
|
||||
@ -42,39 +42,30 @@ func SendEmail(
|
||||
allowUnverifiedNotificationChannel bool,
|
||||
) error {
|
||||
args = mapNotifyUserToArgs(user, args)
|
||||
data := GetTemplateData(translator, args, assetsPrefix, url, messageType, user.PreferredLanguage.String(), colors)
|
||||
data := GetTemplateData(ctx, translator, args, url, messageType, user.PreferredLanguage.String(), colors)
|
||||
template, err := templates.GetParsedTemplate(mailhtml, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(
|
||||
ctx,
|
||||
channels,
|
||||
user,
|
||||
data.Subject,
|
||||
template,
|
||||
emailConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
allowUnverifiedNotificationChannel,
|
||||
triggeringEvent,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func SendSMSTwilio(
|
||||
ctx context.Context,
|
||||
channels ChannelChains,
|
||||
translator *i18n.Translator,
|
||||
user *query.NotifyUser,
|
||||
twilioConfig func(ctx context.Context) (*twilio.Config, error),
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
colors *query.LabelPolicy,
|
||||
assetsPrefix string,
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) Notify {
|
||||
return func(
|
||||
url string,
|
||||
@ -83,18 +74,14 @@ func SendSMSTwilio(
|
||||
allowUnverifiedNotificationChannel bool,
|
||||
) error {
|
||||
args = mapNotifyUserToArgs(user, args)
|
||||
data := GetTemplateData(translator, args, assetsPrefix, url, messageType, user.PreferredLanguage.String(), colors)
|
||||
data := GetTemplateData(ctx, translator, args, url, messageType, user.PreferredLanguage.String(), colors)
|
||||
return generateSms(
|
||||
ctx,
|
||||
channels,
|
||||
user,
|
||||
data.Text,
|
||||
twilioConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
allowUnverifiedNotificationChannel,
|
||||
triggeringEvent,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -102,23 +89,17 @@ func SendSMSTwilio(
|
||||
func SendJSON(
|
||||
ctx context.Context,
|
||||
webhookConfig webhook.Config,
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
channels ChannelChains,
|
||||
serializable interface{},
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) Notify {
|
||||
return func(_ string, _ map[string]interface{}, _ string, _ bool) error {
|
||||
return handleJSON(
|
||||
return handleWebhook(
|
||||
ctx,
|
||||
webhookConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
channels,
|
||||
serializable,
|
||||
triggeringEvent,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,31 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendOTPSMSCode(requestedDomain, origin, code string, expiry time.Duration) error {
|
||||
args := otpArgs(code, origin, requestedDomain, expiry)
|
||||
func (notify Notify) SendOTPSMSCode(ctx context.Context, code string, expiry time.Duration) error {
|
||||
args := otpArgs(ctx, code, expiry)
|
||||
return notify("", args, domain.VerifySMSOTPMessageType, false)
|
||||
}
|
||||
|
||||
func (notify Notify) SendOTPEmailCode(user *query.NotifyUser, url, requestedDomain, origin, code string, expiry time.Duration) error {
|
||||
args := otpArgs(code, origin, requestedDomain, expiry)
|
||||
func (notify Notify) SendOTPEmailCode(ctx context.Context, url, code string, expiry time.Duration) error {
|
||||
args := otpArgs(ctx, code, expiry)
|
||||
return notify(url, args, domain.VerifyEmailOTPMessageType, false)
|
||||
}
|
||||
|
||||
func otpArgs(code, origin, requestedDomain string, expiry time.Duration) map[string]interface{} {
|
||||
func otpArgs(ctx context.Context, code string, expiry time.Duration) map[string]interface{} {
|
||||
args := make(map[string]interface{})
|
||||
args["OTP"] = code
|
||||
args["Origin"] = origin
|
||||
args["Domain"] = requestedDomain
|
||||
args["Origin"] = http_utils.ComposedOrigin(ctx)
|
||||
args["Domain"] = authz.GetInstance(ctx).RequestedDomain()
|
||||
args["Expiry"] = expiry
|
||||
return args
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/console"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendPasswordChange(user *query.NotifyUser, origin string) error {
|
||||
url := console.LoginHintLink(origin, user.PreferredLoginName)
|
||||
func (notify Notify) SendPasswordChange(ctx context.Context, user *query.NotifyUser) error {
|
||||
url := console.LoginHintLink(http_utils.ComposedOrigin(ctx), user.PreferredLoginName)
|
||||
args := make(map[string]interface{})
|
||||
return notify(url, args, domain.PasswordChangeMessageType, true)
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendPasswordCode(user *query.NotifyUser, origin, code, urlTmpl string) error {
|
||||
func (notify Notify) SendPasswordCode(ctx context.Context, user *query.NotifyUser, code, urlTmpl string) error {
|
||||
var url string
|
||||
if urlTmpl == "" {
|
||||
url = login.InitPasswordLink(origin, user.ID, code, user.ResourceOwner)
|
||||
url = login.InitPasswordLink(http_utils.ComposedOrigin(ctx), user.ID, code, user.ResourceOwner)
|
||||
} else {
|
||||
var buf strings.Builder
|
||||
if err := domain.RenderConfirmURLTemplate(&buf, urlTmpl, user.ID, code, user.ResourceOwner); err != nil {
|
||||
|
@ -1,17 +1,19 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/api/ui/login"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendPasswordlessRegistrationLink(user *query.NotifyUser, origin, code, codeID, urlTmpl string) error {
|
||||
func (notify Notify) SendPasswordlessRegistrationLink(ctx context.Context, user *query.NotifyUser, code, codeID, urlTmpl string) error {
|
||||
var url string
|
||||
if urlTmpl == "" {
|
||||
url = domain.PasswordlessInitCodeLink(origin+login.HandlerPrefix+login.EndpointPasswordlessRegistration, user.ID, user.ResourceOwner, codeID, code)
|
||||
url = domain.PasswordlessInitCodeLink(http_utils.ComposedOrigin(ctx)+login.HandlerPrefix+login.EndpointPasswordlessRegistration, user.ID, user.ResourceOwner, codeID, code)
|
||||
} else {
|
||||
var buf strings.Builder
|
||||
if err := domain.RenderPasskeyURLTemplate(&buf, urlTmpl, user.ID, user.ResourceOwner, codeID, code); err != nil {
|
||||
@ -19,6 +21,5 @@ func (notify Notify) SendPasswordlessRegistrationLink(user *query.NotifyUser, or
|
||||
}
|
||||
url = buf.String()
|
||||
}
|
||||
|
||||
return notify(url, nil, domain.PasswordlessRegistrationMessageType, true)
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
http_utils "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@ -80,7 +82,7 @@ func TestNotify_SendPasswordlessRegistrationLink(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, notify := mockNotify()
|
||||
err := notify.SendPasswordlessRegistrationLink(tt.args.user, tt.args.origin, tt.args.code, tt.args.codeID, tt.args.urlTmpl)
|
||||
err := notify.SendPasswordlessRegistrationLink(http_utils.WithComposedOrigin(context.Background(), tt.args.origin), tt.args.user, tt.args.code, tt.args.codeID, tt.args.urlTmpl)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
|
@ -1,13 +1,15 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func (notify Notify) SendPhoneVerificationCode(user *query.NotifyUser, origin, code, requestedDomain string) error {
|
||||
func (notify Notify) SendPhoneVerificationCode(ctx context.Context, code string) error {
|
||||
args := make(map[string]interface{})
|
||||
args["Code"] = code
|
||||
args["Domain"] = requestedDomain
|
||||
args["Domain"] = authz.GetInstance(ctx).RequestedDomain()
|
||||
return notify("", args, domain.VerifyPhoneMessageType, true)
|
||||
}
|
||||
|
@ -1,15 +1,20 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
http_util "github.com/zitadel/zitadel/internal/api/http"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/assets"
|
||||
"github.com/zitadel/zitadel/internal/i18n"
|
||||
"github.com/zitadel/zitadel/internal/notification/templates"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func GetTemplateData(translator *i18n.Translator, translateArgs map[string]interface{}, assetsPrefix, href, msgType, lang string, policy *query.LabelPolicy) templates.TemplateData {
|
||||
func GetTemplateData(ctx context.Context, translator *i18n.Translator, translateArgs map[string]interface{}, href, msgType, lang string, policy *query.LabelPolicy) templates.TemplateData {
|
||||
assetsPrefix := http_util.ComposedOrigin(ctx) + assets.HandlerPrefix
|
||||
templateData := templates.TemplateData{
|
||||
URL: href,
|
||||
PrimaryColor: templates.DefaultPrimaryColor,
|
||||
@ -28,9 +33,6 @@ func GetTemplateData(translator *i18n.Translator, translateArgs map[string]inter
|
||||
if policy.Light.FontColor != "" {
|
||||
templateData.FontColor = policy.Light.FontColor
|
||||
}
|
||||
if assetsPrefix == "" {
|
||||
return templateData
|
||||
}
|
||||
if policy.Light.LogoURL != "" {
|
||||
templateData.LogoURL = fmt.Sprintf("%s/%s/%s", assetsPrefix, policy.ID, policy.Light.LogoURL)
|
||||
}
|
||||
|
@ -6,26 +6,18 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/fs"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/log"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/messages"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func generateEmail(
|
||||
ctx context.Context,
|
||||
channels ChannelChains,
|
||||
user *query.NotifyUser,
|
||||
subject,
|
||||
content string,
|
||||
smtpConfig func(ctx context.Context) (*smtp.Config, error),
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
lastEmail bool,
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) error {
|
||||
content = html.UnescapeString(content)
|
||||
message := &messages.Email{
|
||||
@ -37,23 +29,14 @@ func generateEmail(
|
||||
if lastEmail {
|
||||
message.Recipients = []string{user.LastEmail}
|
||||
}
|
||||
|
||||
channelChain, err := senders.EmailChannels(
|
||||
ctx,
|
||||
smtpConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
emailChannels, _, err := channels.Email(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if channelChain.Len() == 0 {
|
||||
if emailChannels.Len() == 0 {
|
||||
return errors.ThrowPreconditionFailed(nil, "MAIL-83nof", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
return channelChain.HandleMessage(message)
|
||||
return emailChannels.HandleMessage(message)
|
||||
}
|
||||
|
||||
func mapNotifyUserToArgs(user *query.NotifyUser, args map[string]interface{}) map[string]interface{} {
|
||||
|
@ -4,31 +4,26 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/fs"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/log"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/zitadel/zitadel/internal/notification/messages"
|
||||
"github.com/zitadel/zitadel/internal/notification/senders"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
)
|
||||
|
||||
func generateSms(
|
||||
ctx context.Context,
|
||||
channels ChannelChains,
|
||||
user *query.NotifyUser,
|
||||
content string,
|
||||
getTwilioProvider func(ctx context.Context) (*twilio.Config, error),
|
||||
getFileSystemProvider func(ctx context.Context) (*fs.Config, error),
|
||||
getLogProvider func(ctx context.Context) (*log.Config, error),
|
||||
lastPhone bool,
|
||||
triggeringEvent eventstore.Event,
|
||||
successMetricName,
|
||||
failureMetricName string,
|
||||
) error {
|
||||
number := ""
|
||||
twilioConfig, err := getTwilioProvider(ctx)
|
||||
smsChannels, twilioConfig, err := channels.SMS(ctx)
|
||||
logging.OnError(err).Error("could not create sms channel")
|
||||
if smsChannels.Len() == 0 {
|
||||
return errors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
if err == nil {
|
||||
number = twilioConfig.SenderNumber
|
||||
}
|
||||
@ -41,19 +36,5 @@ func generateSms(
|
||||
if lastPhone {
|
||||
message.RecipientPhoneNumber = user.LastPhone
|
||||
}
|
||||
|
||||
channelChain, err := senders.SMSChannels(
|
||||
ctx,
|
||||
twilioConfig,
|
||||
getFileSystemProvider,
|
||||
getLogProvider,
|
||||
successMetricName,
|
||||
failureMetricName,
|
||||
)
|
||||
logging.OnError(err).Error("could not create sms channel")
|
||||
|
||||
if channelChain.Len() == 0 {
|
||||
return errors.ThrowPreconditionFailed(nil, "PHONE-w8nfow", "Errors.Notification.Channels.NotPresent")
|
||||
}
|
||||
return channelChain.HandleMessage(message)
|
||||
return smsChannels.HandleMessage(message)
|
||||
}
|
||||
|
27
internal/notification/types/webhook.go
Normal file
27
internal/notification/types/webhook.go
Normal file
@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/notification/messages"
|
||||
)
|
||||
|
||||
func handleWebhook(
|
||||
ctx context.Context,
|
||||
webhookConfig webhook.Config,
|
||||
channels ChannelChains,
|
||||
serializable interface{},
|
||||
triggeringEvent eventstore.Event,
|
||||
) error {
|
||||
message := &messages.JSON{
|
||||
Serializable: serializable,
|
||||
TriggeringEvent: triggeringEvent,
|
||||
}
|
||||
webhookChannels, err := channels.Webhook(ctx, webhookConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return webhookChannels.HandleMessage(message)
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@ -409,10 +410,11 @@ func NewOTPSMSCheckedEvent(
|
||||
type OTPEmailChallengedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Code *crypto.CryptoValue `json:"code"`
|
||||
Expiry time.Duration `json:"expiry"`
|
||||
ReturnCode bool `json:"returnCode,omitempty"`
|
||||
URLTmpl string `json:"urlTmpl,omitempty"`
|
||||
Code *crypto.CryptoValue `json:"code"`
|
||||
Expiry time.Duration `json:"expiry"`
|
||||
ReturnCode bool `json:"returnCode,omitempty"`
|
||||
URLTmpl string `json:"urlTmpl,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *OTPEmailChallengedEvent) Data() interface{} {
|
||||
@ -427,6 +429,10 @@ func (e *OTPEmailChallengedEvent) SetBaseEvent(base *eventstore.BaseEvent) {
|
||||
e.BaseEvent = *base
|
||||
}
|
||||
|
||||
func (e *OTPEmailChallengedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewOTPEmailChallengedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -441,10 +447,11 @@ func NewOTPEmailChallengedEvent(
|
||||
aggregate,
|
||||
OTPEmailChallengedType,
|
||||
),
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
ReturnCode: returnCode,
|
||||
URLTmpl: urlTmpl,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
ReturnCode: returnCode,
|
||||
URLTmpl: urlTmpl,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@ -244,6 +245,7 @@ type HumanInitialCodeAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
Code *crypto.CryptoValue `json:"code,omitempty"`
|
||||
Expiry time.Duration `json:"expiry,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanInitialCodeAddedEvent) Data() interface{} {
|
||||
@ -254,6 +256,10 @@ func (e *HumanInitialCodeAddedEvent) UniqueConstraints() []*eventstore.EventUniq
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *HumanInitialCodeAddedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewHumanInitialCodeAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -266,8 +272,9 @@ func NewHumanInitialCodeAddedEvent(
|
||||
aggregate,
|
||||
HumanInitialCodeAddedType,
|
||||
),
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@ -122,10 +123,11 @@ func HumanEmailVerificationFailedEventMapper(event *repository.Event) (eventstor
|
||||
type HumanEmailCodeAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Code *crypto.CryptoValue `json:"code,omitempty"`
|
||||
Expiry time.Duration `json:"expiry,omitempty"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
Code *crypto.CryptoValue `json:"code,omitempty"`
|
||||
Expiry time.Duration `json:"expiry,omitempty"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanEmailCodeAddedEvent) Data() interface{} {
|
||||
@ -136,6 +138,10 @@ func (e *HumanEmailCodeAddedEvent) UniqueConstraints() []*eventstore.EventUnique
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *HumanEmailCodeAddedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewHumanEmailCodeAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -159,10 +165,11 @@ func NewHumanEmailCodeAddedEventV2(
|
||||
aggregate,
|
||||
HumanEmailCodeAddedType,
|
||||
),
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
URLTemplate: urlTemplate,
|
||||
CodeReturned: codeReturned,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
URLTemplate: urlTemplate,
|
||||
CodeReturned: codeReturned,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@ -317,11 +318,12 @@ func HumanPasswordlessInitCodeAddedEventMapper(event *repository.Event) (eventst
|
||||
type HumanPasswordlessInitCodeRequestedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
ID string `json:"id"`
|
||||
Code *crypto.CryptoValue `json:"code"`
|
||||
Expiry time.Duration `json:"expiry"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Code *crypto.CryptoValue `json:"code"`
|
||||
Expiry time.Duration `json:"expiry"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanPasswordlessInitCodeRequestedEvent) Data() interface{} {
|
||||
@ -332,6 +334,10 @@ func (e *HumanPasswordlessInitCodeRequestedEvent) UniqueConstraints() []*eventst
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *HumanPasswordlessInitCodeRequestedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewHumanPasswordlessInitCodeRequestedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -347,11 +353,12 @@ func NewHumanPasswordlessInitCodeRequestedEvent(
|
||||
aggregate,
|
||||
HumanPasswordlessInitCodeRequestedType,
|
||||
),
|
||||
ID: id,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
URLTemplate: urlTmpl,
|
||||
CodeReturned: codeReturned,
|
||||
ID: id,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
URLTemplate: urlTmpl,
|
||||
CodeReturned: codeReturned,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
)
|
||||
|
||||
@ -29,10 +29,11 @@ type HumanPasswordChangedEvent struct {
|
||||
|
||||
// New events only use EncodedHash. However, the secret field
|
||||
// is preserved to handle events older than the switch to Passwap.
|
||||
Secret *crypto.CryptoValue `json:"secret,omitempty"`
|
||||
EncodedHash string `json:"encodedHash,omitempty"`
|
||||
ChangeRequired bool `json:"changeRequired"`
|
||||
UserAgentID string `json:"userAgentID,omitempty"`
|
||||
Secret *crypto.CryptoValue `json:"secret,omitempty"`
|
||||
EncodedHash string `json:"encodedHash,omitempty"`
|
||||
ChangeRequired bool `json:"changeRequired"`
|
||||
UserAgentID string `json:"userAgentID,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanPasswordChangedEvent) Data() interface{} {
|
||||
@ -43,6 +44,10 @@ func (e *HumanPasswordChangedEvent) UniqueConstraints() []*eventstore.EventUniqu
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *HumanPasswordChangedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewHumanPasswordChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -56,9 +61,10 @@ func NewHumanPasswordChangedEvent(
|
||||
aggregate,
|
||||
HumanPasswordChangedType,
|
||||
),
|
||||
EncodedHash: encodeHash,
|
||||
ChangeRequired: changeRequired,
|
||||
UserAgentID: userAgentID,
|
||||
EncodedHash: encodeHash,
|
||||
ChangeRequired: changeRequired,
|
||||
UserAgentID: userAgentID,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,11 +83,12 @@ func HumanPasswordChangedEventMapper(event *repository.Event) (eventstore.Event,
|
||||
type HumanPasswordCodeAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Code *crypto.CryptoValue `json:"code,omitempty"`
|
||||
Expiry time.Duration `json:"expiry,omitempty"`
|
||||
NotificationType domain.NotificationType `json:"notificationType,omitempty"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
Code *crypto.CryptoValue `json:"code,omitempty"`
|
||||
Expiry time.Duration `json:"expiry,omitempty"`
|
||||
NotificationType domain.NotificationType `json:"notificationType,omitempty"`
|
||||
URLTemplate string `json:"url_template,omitempty"`
|
||||
CodeReturned bool `json:"code_returned,omitempty"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanPasswordCodeAddedEvent) Data() interface{} {
|
||||
@ -92,6 +99,10 @@ func (e *HumanPasswordCodeAddedEvent) UniqueConstraints() []*eventstore.EventUni
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *HumanPasswordCodeAddedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewHumanPasswordCodeAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -117,11 +128,12 @@ func NewHumanPasswordCodeAddedEventV2(
|
||||
aggregate,
|
||||
HumanPasswordCodeAddedType,
|
||||
),
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
NotificationType: notificationType,
|
||||
URLTemplate: urlTemplate,
|
||||
CodeReturned: codeReturned,
|
||||
Code: code,
|
||||
Expiry: expiry,
|
||||
NotificationType: notificationType,
|
||||
URLTemplate: urlTemplate,
|
||||
CodeReturned: codeReturned,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||
)
|
||||
|
||||
@ -315,6 +315,7 @@ type DomainClaimedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
oldUserName string
|
||||
userLoginMustBeDomain bool
|
||||
}
|
||||
@ -330,6 +331,10 @@ func (e *DomainClaimedEvent) UniqueConstraints() []*eventstore.EventUniqueConstr
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DomainClaimedEvent) TriggerOrigin() string {
|
||||
return e.TriggeredAtOrigin
|
||||
}
|
||||
|
||||
func NewDomainClaimedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@ -346,6 +351,7 @@ func NewDomainClaimedEvent(
|
||||
UserName: userName,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
TriggeredAtOrigin: http.ComposedOrigin(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user