mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-27 01:32:15 +00:00
feat: added xoauth for smtp (#11239)
# Which Problems Are Solved - Some mail providers (e.g.: MS Exchange) have deprecated plain auth # How the Problems Are Solved Adds XOauth2 auth option to SMPT - SMTP config now can contain XOAuth2 auth config - Proto files are updated to have a oneof for configuration selection. Old fields for configuring plain auth are still available not to create a breaking change. These can be removed in the future. - Columns are added to the database to persist the config # Additional Changes none # Additional Context Replace this example with links to related issues, discussions, discord threads, or other sources with more context. Use the Closing #issue syntax for issues that are resolved with this PR. - Closes #8042 --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Tim Möhlmann <[email protected]>
This commit is contained in:
co-authored by
Copilot
Tim Möhlmann
parent
96bbd6a65c
commit
3fc0ef2506
@@ -1406,6 +1406,8 @@ func TestServer_TestInstanceSecretGeneratorSettingsReduces(t *testing.T) {
|
||||
),
|
||||
)
|
||||
require.NoError(collect, err)
|
||||
require.NotNil(collect, setting)
|
||||
|
||||
// ClientSecret
|
||||
assert.Equal(collect, uint(64), *setting.ClientSecret.Length)
|
||||
assert.Equal(collect, true, *setting.ClientSecret.IncludeLowerLetters)
|
||||
|
||||
@@ -16,14 +16,18 @@ ZITADEL integrates with Twilio as SMS provider.
|
||||
|
||||
## SMTP providers
|
||||
|
||||
Integration with most SMTP providers is possible through a generic SMTP provider template that allows you to configure custom SMTP providers.
|
||||
Additionally, integration templates are available for:
|
||||
For easy configuration, there are some integration templates available such as:
|
||||
|
||||
- Amazon SES
|
||||
- Mailgun
|
||||
- Mailjet
|
||||
- Postmark
|
||||
- Sendgrid
|
||||
- SendGrid
|
||||
- ...
|
||||
|
||||
Aside from those, it is also possible to configure a generic SMTP provider. With a generic SMTP provider you specify what
|
||||
the SMTP server, username and what kind of auth method you want to use. Currently, the Console only supports plain auth.
|
||||
However, with [the API's](https://zitadel.com/docs/apis/resources/admin/admin-service-add-email-provider-smtp) you can
|
||||
configure XOAUTH2 as well.
|
||||
|
||||
:::info Default Provider ZITADEL Cloud
|
||||
A default SMTP provider is configured for ZITADEL Cloud customers.
|
||||
@@ -46,7 +50,7 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
|
||||
curl -L 'https://${CUSTOM_DOMAIN}/admin/v1/sms/http' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Authorization: Bearer <TOKEN>' \
|
||||
-H 'Authorization: Bearer ${TOKEN}' \
|
||||
-d '{
|
||||
"endpoint": "http://relay.example.com/provider",
|
||||
"description": "provider description"
|
||||
@@ -63,7 +67,7 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
|
||||
curl -L 'https://${CUSTOM_DOMAIN}/admin/v1/sms/:id/_activate' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Authorization: Bearer <TOKEN>' \
|
||||
-H 'Authorization: Bearer ${TOKEN}' \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
@@ -80,7 +84,7 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
|
||||
curl -L 'https://${CUSTOM_DOMAIN}/admin/v1/email/http' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Authorization: Bearer <TOKEN>' \
|
||||
-H 'Authorization: Bearer ${TOKEN}' \
|
||||
-d '{
|
||||
"endpoint": "http://relay.example.com/provider",
|
||||
"description": "provider description"
|
||||
@@ -97,7 +101,7 @@ A provider with HTTP type will send the messages and the data to a pre-defined w
|
||||
curl -L 'https://${CUSTOM_DOMAIN}/admin/v1/email/:id/_activate' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Authorization: Bearer <TOKEN>' \
|
||||
-H 'Authorization: Bearer ${TOKEN}' \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ func httpToPb(http *query.HTTP) *settings_pb.EmailProvider_Http {
|
||||
}
|
||||
|
||||
func smtpToPb(config *query.SMTP) *settings_pb.EmailProvider_Smtp {
|
||||
return &settings_pb.EmailProvider_Smtp{
|
||||
ret := &settings_pb.EmailProvider_Smtp{
|
||||
Smtp: &settings_pb.EmailProviderSMTP{
|
||||
Tls: config.TLS,
|
||||
Host: config.Host,
|
||||
@@ -85,10 +85,34 @@ func smtpToPb(config *query.SMTP) *settings_pb.EmailProvider_Smtp {
|
||||
ReplyToAddress: config.ReplyToAddress,
|
||||
},
|
||||
}
|
||||
|
||||
if config.PlainAuth != nil {
|
||||
ret.Smtp.Auth = &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
}
|
||||
}
|
||||
if config.XOAuth2Auth != nil {
|
||||
xoauth2 := &settings_pb.EmailProviderSMTP_Xoauth2{
|
||||
Xoauth2: &settings_pb.SMTPXOAuth2Auth{
|
||||
TokenEndpoint: config.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: config.XOAuth2Auth.Scopes,
|
||||
},
|
||||
}
|
||||
if config.XOAuth2Auth.ClientCredentials != nil {
|
||||
xoauth2.Xoauth2.OAuth2Type = &settings_pb.SMTPXOAuth2Auth_ClientCredentials_{
|
||||
ClientCredentials: &settings_pb.SMTPXOAuth2Auth_ClientCredentials{
|
||||
ClientId: config.XOAuth2Auth.ClientCredentials.ClientId,
|
||||
},
|
||||
}
|
||||
}
|
||||
ret.Smtp.Auth = xoauth2
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func addEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.AddEmailProviderSMTPRequest) *command.AddSMTPConfig {
|
||||
return &command.AddSMTPConfig{
|
||||
cmd := &command.AddSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
@@ -97,12 +121,41 @@ func addEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.AddEmailPro
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
|
||||
switch v := req.Auth.(type) {
|
||||
case *admin_pb.AddEmailProviderSMTPRequest_None:
|
||||
// Nothing to do, no auth is required
|
||||
case *admin_pb.AddEmailProviderSMTPRequest_Plain:
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: v.Plain.Password,
|
||||
}
|
||||
case *admin_pb.AddEmailProviderSMTPRequest_Xoauth2:
|
||||
if xoauth2, ok := v.Xoauth2.OAuth2Type.(*admin_pb.SMTPXOAuth2Auth_ClientCredentials_); ok {
|
||||
cmd.XOAuth2Auth = &command.XOAuth2Auth{
|
||||
TokenEndpoint: v.Xoauth2.TokenEndpoint,
|
||||
Scopes: v.Xoauth2.Scopes,
|
||||
ClientCredentialsAuth: &command.OAuth2ClientCredentials{
|
||||
ClientId: xoauth2.ClientCredentials.ClientId,
|
||||
ClientSecret: xoauth2.ClientCredentials.ClientSecret,
|
||||
},
|
||||
}
|
||||
}
|
||||
default:
|
||||
// ensure backwards compatibility
|
||||
//nolint:staticcheck
|
||||
if req.User != "" || req.Password != "" {
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func updateEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.UpdateEmailProviderSMTPRequest) *command.ChangeSMTPConfig {
|
||||
return &command.ChangeSMTPConfig{
|
||||
cmd := &command.ChangeSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
ID: req.Id,
|
||||
Description: req.Description,
|
||||
@@ -112,8 +165,41 @@ func updateEmailProviderSMTPToConfig(ctx context.Context, req *admin_pb.UpdateEm
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
|
||||
switch v := req.Auth.(type) {
|
||||
case *admin_pb.UpdateEmailProviderSMTPRequest_None:
|
||||
// Nothing to do, no auth is required
|
||||
case *admin_pb.UpdateEmailProviderSMTPRequest_Plain:
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: v.Plain.Password,
|
||||
}
|
||||
case *admin_pb.UpdateEmailProviderSMTPRequest_Xoauth2:
|
||||
cmd.XOAuth2Auth = xoauth2ToCmd(v)
|
||||
default:
|
||||
// ensure backwards compatibility
|
||||
if req.User != "" || req.Password != "" {
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func xoauth2ToCmd(xoauth2 *admin_pb.UpdateEmailProviderSMTPRequest_Xoauth2) *command.XOAuth2Auth {
|
||||
cmd := &command.XOAuth2Auth{
|
||||
TokenEndpoint: xoauth2.Xoauth2.TokenEndpoint,
|
||||
Scopes: xoauth2.Xoauth2.Scopes,
|
||||
}
|
||||
if v, ok := xoauth2.Xoauth2.OAuth2Type.(*admin_pb.SMTPXOAuth2Auth_ClientCredentials_); ok {
|
||||
cmd.ClientCredentialsAuth = &command.OAuth2ClientCredentials{
|
||||
ClientId: v.ClientCredentials.ClientId,
|
||||
ClientSecret: v.ClientCredentials.ClientSecret,
|
||||
}
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func addEmailProviderHTTPToConfig(ctx context.Context, req *admin_pb.AddEmailProviderHTTPRequest) *command.AddSMTPConfigHTTP {
|
||||
@@ -137,14 +223,49 @@ func updateEmailProviderHTTPToConfig(ctx context.Context, req *admin_pb.UpdateEm
|
||||
}
|
||||
|
||||
func testEmailProviderSMTPToConfig(req *admin_pb.TestEmailProviderSMTPRequest) *smtp.Config {
|
||||
return &smtp.Config{
|
||||
cfg := &smtp.Config{
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
Host: req.Host,
|
||||
},
|
||||
}
|
||||
|
||||
switch v := req.Auth.(type) {
|
||||
case *admin_pb.TestEmailProviderSMTPRequest_None:
|
||||
// Nothing to do, no auth is required
|
||||
case *admin_pb.TestEmailProviderSMTPRequest_Plain:
|
||||
cfg.SMTP.PlainAuth = &smtp.PlainAuthConfig{
|
||||
User: req.User,
|
||||
Password: v.Plain.Password,
|
||||
}
|
||||
case *admin_pb.TestEmailProviderSMTPRequest_Xoauth2:
|
||||
cfg.SMTP.XOAuth2Auth = xoauth2ToSmtp(v, req.User)
|
||||
default:
|
||||
// ensure backwards compatibility
|
||||
if req.User != "" || req.Password != "" {
|
||||
cfg.SMTP.PlainAuth = &smtp.PlainAuthConfig{
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func xoauth2ToSmtp(xoauth2 *admin_pb.TestEmailProviderSMTPRequest_Xoauth2, user string) *smtp.XOAuth2AuthConfig {
|
||||
cfg := &smtp.XOAuth2AuthConfig{
|
||||
User: user,
|
||||
TokenEndpoint: xoauth2.Xoauth2.TokenEndpoint,
|
||||
Scopes: xoauth2.Xoauth2.Scopes,
|
||||
}
|
||||
if v, ok := xoauth2.Xoauth2.OAuth2Type.(*admin_pb.SMTPXOAuth2Auth_ClientCredentials_); ok {
|
||||
cfg.ClientCredentialsAuth = &smtp.OAuth2ClientCredentials{
|
||||
ClientId: v.ClientCredentials.ClientId,
|
||||
ClientSecret: v.ClientCredentials.ClientSecret,
|
||||
}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
object_pb "github.com/zitadel/zitadel/pkg/grpc/object"
|
||||
@@ -85,6 +86,7 @@ func Test_emailProvidersToPb(t *testing.T) {
|
||||
ReplyToAddress: "address",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
PlainAuth: &query.PlainAuth{},
|
||||
},
|
||||
HTTPConfig: nil,
|
||||
State: 1,
|
||||
@@ -125,6 +127,9 @@ func Test_emailProvidersToPb(t *testing.T) {
|
||||
Host: "host",
|
||||
User: "user",
|
||||
ReplyToAddress: "address",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -184,6 +189,7 @@ func Test_emailProviderToProviderPb(t *testing.T) {
|
||||
ReplyToAddress: "address",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
PlainAuth: &query.PlainAuth{},
|
||||
},
|
||||
HTTPConfig: &query.HTTP{
|
||||
Endpoint: "endpoint",
|
||||
@@ -210,6 +216,9 @@ func Test_emailProviderToProviderPb(t *testing.T) {
|
||||
Host: "host",
|
||||
User: "user",
|
||||
ReplyToAddress: "address",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -254,7 +263,7 @@ func Test_emailProviderToProviderPb(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := emailProviderToProviderPb(tt.args.req)
|
||||
assert.Equal(t, tt.res, got)
|
||||
assert.EqualValues(t, tt.res, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -363,6 +372,7 @@ func Test_smtpToPb(t *testing.T) {
|
||||
TLS: true,
|
||||
Host: "host",
|
||||
User: "user",
|
||||
PlainAuth: &query.PlainAuth{},
|
||||
ReplyToAddress: "address",
|
||||
},
|
||||
},
|
||||
@@ -374,6 +384,74 @@ func Test_smtpToPb(t *testing.T) {
|
||||
Host: "host",
|
||||
User: "user",
|
||||
ReplyToAddress: "address",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy auth must still be supported",
|
||||
args: args{
|
||||
req: &query.SMTP{
|
||||
User: "user",
|
||||
PlainAuth: &query.PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: &settings_pb.EmailProvider_Smtp{
|
||||
Smtp: &settings_pb.EmailProviderSMTP{
|
||||
User: "user",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "plain auth must map to plain",
|
||||
args: args{
|
||||
req: &query.SMTP{
|
||||
User: "plain-user",
|
||||
PlainAuth: &query.PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: &settings_pb.EmailProvider_Smtp{
|
||||
Smtp: &settings_pb.EmailProviderSMTP{
|
||||
User: "plain-user",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Plain{
|
||||
Plain: &settings_pb.SMTPPlainAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "xoauth2 auth must map to xoauth2",
|
||||
args: args{
|
||||
req: &query.SMTP{
|
||||
User: "xoauth2-user",
|
||||
XOAuth2Auth: &query.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
ClientCredentials: &query.XOAuthClientCredentials{
|
||||
ClientId: "my-client",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &settings_pb.EmailProvider_Smtp{
|
||||
Smtp: &settings_pb.EmailProviderSMTP{
|
||||
User: "xoauth2-user",
|
||||
Auth: &settings_pb.EmailProviderSMTP_Xoauth2{
|
||||
Xoauth2: &settings_pb.SMTPXOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
OAuth2Type: &settings_pb.SMTPXOAuth2Auth_ClientCredentials_{
|
||||
ClientCredentials: &settings_pb.SMTPXOAuth2Auth_ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -412,17 +490,90 @@ func Test_addEmailProviderSMTPToConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: &command.AddSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
Description: "description",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
ResourceOwner: "instance",
|
||||
Description: "description",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
Tls: true,
|
||||
From: "sender",
|
||||
FromName: "sendername",
|
||||
ReplyToAddress: "address",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy auth (username password) should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.AddEmailProviderSMTPRequest{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
res: &command.AddSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
User: "user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "plain auth should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.AddEmailProviderSMTPRequest{
|
||||
User: "plain-user",
|
||||
Auth: &admin_pb.AddEmailProviderSMTPRequest_Plain{
|
||||
Plain: &admin_pb.SMTPPlainAuth{
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &command.AddSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
User: "plain-user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "xoauth2 auth should map to xoauth2",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.AddEmailProviderSMTPRequest{
|
||||
User: "xoauth2-user",
|
||||
Auth: &admin_pb.AddEmailProviderSMTPRequest_Xoauth2{
|
||||
Xoauth2: &admin_pb.SMTPXOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
OAuth2Type: &admin_pb.SMTPXOAuth2Auth_ClientCredentials_{
|
||||
ClientCredentials: &admin_pb.SMTPXOAuth2Auth_ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &command.AddSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
User: "xoauth2-user",
|
||||
XOAuth2Auth: &command.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
ClientCredentialsAuth: &command.OAuth2ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -459,18 +610,97 @@ func Test_updateEmailProviderSMTPToConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: &command.ChangeSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
ID: "id",
|
||||
Description: "description",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
ResourceOwner: "instance",
|
||||
ID: "id",
|
||||
Description: "description",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
Tls: true,
|
||||
From: "sender",
|
||||
FromName: "sendername",
|
||||
ReplyToAddress: "address",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy auth (username password) should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.UpdateEmailProviderSMTPRequest{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
Id: "id",
|
||||
},
|
||||
},
|
||||
res: &command.ChangeSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
ID: "id",
|
||||
User: "user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "plain auth should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.UpdateEmailProviderSMTPRequest{
|
||||
Id: "id",
|
||||
User: "plain-user",
|
||||
Auth: &admin_pb.UpdateEmailProviderSMTPRequest_Plain{
|
||||
Plain: &admin_pb.SMTPPlainAuth{
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &command.ChangeSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
ID: "id",
|
||||
User: "plain-user",
|
||||
PlainAuth: &command.PlainAuth{
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "xoauth2 auth should map to xoauth2",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.UpdateEmailProviderSMTPRequest{
|
||||
Id: "id",
|
||||
User: "xoauth2-user",
|
||||
Auth: &admin_pb.UpdateEmailProviderSMTPRequest_Xoauth2{
|
||||
Xoauth2: &admin_pb.SMTPXOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
OAuth2Type: &admin_pb.SMTPXOAuth2Auth_ClientCredentials_{
|
||||
ClientCredentials: &admin_pb.SMTPXOAuth2Auth_ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &command.ChangeSMTPConfig{
|
||||
ResourceOwner: "instance",
|
||||
ID: "id",
|
||||
User: "xoauth2-user",
|
||||
XOAuth2Auth: &command.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
ClientCredentialsAuth: &command.OAuth2ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -552,3 +782,122 @@ func Test_updateEmailProviderHTTPToConfig(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_testEmailProviderSMTPToConfig(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *admin_pb.TestEmailProviderSMTPRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
res *smtp.Config
|
||||
}{
|
||||
{
|
||||
name: "all fields filled",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.TestEmailProviderSMTPRequest{
|
||||
SenderAddress: "sender",
|
||||
SenderName: "sendername",
|
||||
Tls: true,
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
res: &smtp.Config{
|
||||
Tls: true,
|
||||
From: "sender",
|
||||
FromName: "sendername",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy auth (username password) should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.TestEmailProviderSMTPRequest{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
res: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "plain auth should map to plain",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.TestEmailProviderSMTPRequest{
|
||||
User: "plain-user",
|
||||
Auth: &admin_pb.TestEmailProviderSMTPRequest_Plain{
|
||||
Plain: &admin_pb.SMTPPlainAuth{
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "plain-user",
|
||||
Password: "other_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "xoauth2 auth should map to xoauth2",
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instance"),
|
||||
req: &admin_pb.TestEmailProviderSMTPRequest{
|
||||
User: "xoauth2-user",
|
||||
Auth: &admin_pb.TestEmailProviderSMTPRequest_Xoauth2{
|
||||
Xoauth2: &admin_pb.SMTPXOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
OAuth2Type: &admin_pb.SMTPXOAuth2Auth_ClientCredentials_{
|
||||
ClientCredentials: &admin_pb.SMTPXOAuth2Auth_ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
XOAuth2Auth: &smtp.XOAuth2AuthConfig{
|
||||
User: "xoauth2-user",
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scopes"},
|
||||
ClientCredentialsAuth: &smtp.OAuth2ClientCredentials{
|
||||
ClientId: "my-client",
|
||||
ClientSecret: "some-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := testEmailProviderSMTPToConfig(tt.args.req)
|
||||
assert.Equal(t, tt.res, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +133,9 @@ func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: use [addEmailProviderSMTPToConfig] instead
|
||||
func addSMTPToConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) *command.AddSMTPConfig {
|
||||
return &command.AddSMTPConfig{
|
||||
cmd := &command.AddSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
Description: req.Description,
|
||||
Tls: req.Tls,
|
||||
@@ -143,12 +144,20 @@ func addSMTPToConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) *c
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
|
||||
if req.User != "" || req.Password != "" {
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Deprecated: use [updateEmailProviderSMTPToConfig] instead
|
||||
func updateSMTPToConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) *command.ChangeSMTPConfig {
|
||||
return &command.ChangeSMTPConfig{
|
||||
cmd := &command.ChangeSMTPConfig{
|
||||
ResourceOwner: authz.GetInstance(ctx).InstanceID(),
|
||||
ID: req.Id,
|
||||
Description: req.Description,
|
||||
@@ -158,26 +167,35 @@ func updateSMTPToConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigReque
|
||||
ReplyToAddress: req.ReplyToAddress,
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigToPb(smtp *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
if smtp.SMTPConfig != nil {
|
||||
return &settings_pb.SMTPConfig{
|
||||
Description: smtp.Description,
|
||||
Tls: smtp.SMTPConfig.TLS,
|
||||
SenderAddress: smtp.SMTPConfig.SenderAddress,
|
||||
SenderName: smtp.SMTPConfig.SenderName,
|
||||
ReplyToAddress: smtp.SMTPConfig.ReplyToAddress,
|
||||
Host: smtp.SMTPConfig.Host,
|
||||
User: smtp.SMTPConfig.User,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.ResourceOwner),
|
||||
Id: smtp.ID,
|
||||
State: settings_pb.SMTPConfigState(smtp.State),
|
||||
if req.User != "" || req.Password != "" {
|
||||
cmd.PlainAuth = &command.PlainAuth{
|
||||
Password: req.Password,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Deprecated: use [smtpToPb] instead.
|
||||
func SMTPConfigToPb(smtp *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
if smtp.SMTPConfig == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &settings_pb.SMTPConfig{
|
||||
Description: smtp.Description,
|
||||
Tls: smtp.SMTPConfig.TLS,
|
||||
SenderAddress: smtp.SMTPConfig.SenderAddress,
|
||||
SenderName: smtp.SMTPConfig.SenderName,
|
||||
ReplyToAddress: smtp.SMTPConfig.ReplyToAddress,
|
||||
Host: smtp.SMTPConfig.Host,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.ResourceOwner),
|
||||
Id: smtp.ID,
|
||||
State: settings_pb.SMTPConfigState(smtp.State),
|
||||
User: smtp.SMTPConfig.User,
|
||||
}
|
||||
}
|
||||
|
||||
func SecurityPolicyToPb(policy *query.SecurityPolicy) *settings_pb.SecurityPolicy {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
// Deprecated: use [GetEmailProvider] instead.
|
||||
func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigRequest) (*admin_pb.GetSMTPConfigResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigActive(ctx, authz.GetInstance(ctx).InstanceID())
|
||||
if err != nil {
|
||||
@@ -19,6 +20,7 @@ func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigR
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [GetEmailProviderById] instead.
|
||||
func (s *Server) GetSMTPConfigById(ctx context.Context, req *admin_pb.GetSMTPConfigByIdRequest) (*admin_pb.GetSMTPConfigByIdResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigByID(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
@@ -29,6 +31,7 @@ func (s *Server) GetSMTPConfigById(ctx context.Context, req *admin_pb.GetSMTPCon
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [AddEmailProviderSMTP] instead.
|
||||
func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigRequest) (*admin_pb.AddSMTPConfigResponse, error) {
|
||||
config := addSMTPToConfig(ctx, req)
|
||||
if err := s.command.AddSMTPConfig(ctx, config); err != nil {
|
||||
@@ -40,6 +43,7 @@ func (s *Server) AddSMTPConfig(ctx context.Context, req *admin_pb.AddSMTPConfigR
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [UpdateEmailProviderSMTP] instead.
|
||||
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
|
||||
config := updateSMTPToConfig(ctx, req)
|
||||
if err := s.command.ChangeSMTPConfig(ctx, config); err != nil {
|
||||
@@ -50,6 +54,7 @@ func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPC
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [RemoveEmailProviderSMTP] instead.
|
||||
func (s *Server) RemoveSMTPConfig(ctx context.Context, req *admin_pb.RemoveSMTPConfigRequest) (*admin_pb.RemoveSMTPConfigResponse, error) {
|
||||
details, err := s.command.RemoveSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
@@ -60,6 +65,7 @@ func (s *Server) RemoveSMTPConfig(ctx context.Context, req *admin_pb.RemoveSMTPC
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [UpdateEmailProviderSMTPPassword] instead.
|
||||
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.Password)
|
||||
if err != nil {
|
||||
@@ -70,6 +76,7 @@ func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.Upd
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [ListEmailProviders] instead.
|
||||
func (s *Server) ListSMTPConfigs(ctx context.Context, req *admin_pb.ListSMTPConfigsRequest) (*admin_pb.ListSMTPConfigsResponse, error) {
|
||||
queries, err := listSMTPConfigsToModel(req)
|
||||
if err != nil {
|
||||
@@ -85,6 +92,7 @@ func (s *Server) ListSMTPConfigs(ctx context.Context, req *admin_pb.ListSMTPConf
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [ActivateEmailProvider] instead.
|
||||
func (s *Server) ActivateSMTPConfig(ctx context.Context, req *admin_pb.ActivateSMTPConfigRequest) (*admin_pb.ActivateSMTPConfigResponse, error) {
|
||||
result, err := s.command.ActivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
@@ -96,6 +104,7 @@ func (s *Server) ActivateSMTPConfig(ctx context.Context, req *admin_pb.ActivateS
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [DeactivateEmailProvider] instead.
|
||||
func (s *Server) DeactivateSMTPConfig(ctx context.Context, req *admin_pb.DeactivateSMTPConfigRequest) (*admin_pb.DeactivateSMTPConfigResponse, error) {
|
||||
result, err := s.command.DeactivateSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id)
|
||||
if err != nil {
|
||||
@@ -107,6 +116,7 @@ func (s *Server) DeactivateSMTPConfig(ctx context.Context, req *admin_pb.Deactiv
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [TestEmailProviderSMTPById] instead.
|
||||
func (s *Server) TestSMTPConfigById(ctx context.Context, req *admin_pb.TestSMTPConfigByIdRequest) (*admin_pb.TestSMTPConfigByIdResponse, error) {
|
||||
err := s.command.TestSMTPConfigById(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress)
|
||||
if err != nil {
|
||||
@@ -116,14 +126,20 @@ func (s *Server) TestSMTPConfigById(ctx context.Context, req *admin_pb.TestSMTPC
|
||||
return &admin_pb.TestSMTPConfigByIdResponse{}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use [TestEmailProviderSMTP] instead.
|
||||
func (s *Server) TestSMTPConfig(ctx context.Context, req *admin_pb.TestSMTPConfigRequest) (*admin_pb.TestSMTPConfigResponse, error) {
|
||||
config := smtp.Config{}
|
||||
config.Tls = req.Tls
|
||||
config.From = req.SenderAddress
|
||||
config.FromName = req.SenderName
|
||||
config.SMTP.Host = req.Host
|
||||
config.SMTP.User = req.User
|
||||
config.SMTP.Password = req.Password
|
||||
config := smtp.Config{
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: req.User,
|
||||
Password: req.Password,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := s.command.TestSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress, &config)
|
||||
if err != nil {
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestListInstances(t *testing.T) {
|
||||
|
||||
orgOwnerCtx := inst.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
relTableState := integration.RelationalTablesEnableMatrix()
|
||||
relTableState := integration.RelationalTablesEnableMatrix(t, ctx, ctxWithSysAuthZ)
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
@@ -222,16 +222,13 @@ func TestListInstances(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, stateCase := range relTableState {
|
||||
integration.EnsureInstanceFeature(t, ctx, inst, stateCase.FeatureSet, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.Equal(tCollect, stateCase.FeatureSet.GetEnableRelationalTables(), got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
|
||||
for _, tc := range tt {
|
||||
// TODO(IAM-Marco): Fix this test for relational case when permission checks are in place (see https://github.com/zitadel/zitadel/issues/10917)
|
||||
if tc.testName == "when unauthZ context should return unauthZ error" && stateCase.State == "when relational tables are enabled" {
|
||||
if tc.testName == "when unauthZ context should return unauthZ error" && stateCase.Name == "when relational tables are enabled" {
|
||||
continue
|
||||
}
|
||||
t.Run(fmt.Sprintf("%s - %s", stateCase.State, tc.testName), func(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s - %s", stateCase.Name, tc.testName), func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2.ListInstances(tc.inputContext, tc.inputRequest)
|
||||
|
||||
@@ -251,7 +248,6 @@ func TestListInstances(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestListCustomDomains(t *testing.T) {
|
||||
|
||||
@@ -34,9 +34,12 @@ func TestAddCustomDomain(t *testing.T) {
|
||||
|
||||
relationalInst := integration.NewInstance(ctxWithSysAuthZ)
|
||||
iamOwnerRelationalCtx := relationalInst.WithAuthorizationToken(context.Background(), integration.UserTypeIAMOwner)
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, relationalInst, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)}, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
integration.EnsureInstanceFeature(t, ctxWithSysAuthZ, relationalInst,
|
||||
&feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)},
|
||||
func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.True(tCollect, got.EnableRelationalTables.GetEnabled())
|
||||
},
|
||||
)
|
||||
|
||||
t.Cleanup(func() {
|
||||
inst.Client.InstanceV2Beta.DeleteInstance(ctxWithSysAuthZ, &instance.DeleteInstanceRequest{InstanceId: inst.ID()})
|
||||
|
||||
@@ -140,7 +140,7 @@ func TestListInstances(t *testing.T) {
|
||||
|
||||
orgOwnerCtx := inst.WithAuthorizationToken(context.Background(), integration.UserTypeOrgOwner)
|
||||
|
||||
relTableState := integration.RelationalTablesEnableMatrix()
|
||||
relTableState := integration.RelationalTablesEnableMatrix(t, ctx, ctxWithSysAuthZ)
|
||||
|
||||
tt := []struct {
|
||||
testName string
|
||||
@@ -196,12 +196,8 @@ func TestListInstances(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, stateCase := range relTableState {
|
||||
integration.EnsureInstanceFeature(t, ctx, inst, stateCase.FeatureSet, func(tCollect *assert.CollectT, got *feature.GetInstanceFeaturesResponse) {
|
||||
assert.Equal(tCollect, stateCase.FeatureSet.GetEnableRelationalTables(), got.EnableRelationalTables.GetEnabled())
|
||||
})
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(fmt.Sprintf("%s - %s", stateCase.State, tc.testName), func(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("%s - %s", stateCase.Name, tc.testName), func(t *testing.T) {
|
||||
// Test
|
||||
res, err := inst.Client.InstanceV2Beta.ListInstances(tc.inputContext, tc.inputRequest)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -520,6 +520,14 @@ func setupSMTPSettings(commands *Commands, validations *[]preparation.Validation
|
||||
if smtpConfig == nil {
|
||||
return
|
||||
}
|
||||
var username string
|
||||
var pwd []byte
|
||||
if smtpConfig.SMTP.PlainAuth != nil {
|
||||
username = smtpConfig.SMTP.PlainAuth.User
|
||||
if smtpConfig.SMTP.PlainAuth != nil {
|
||||
pwd = []byte(smtpConfig.SMTP.PlainAuth.Password)
|
||||
}
|
||||
}
|
||||
*validations = append(*validations,
|
||||
commands.prepareAddAndActivateSMTPConfig(
|
||||
instanceAgg,
|
||||
@@ -528,8 +536,8 @@ func setupSMTPSettings(commands *Commands, validations *[]preparation.Validation
|
||||
smtpConfig.FromName,
|
||||
smtpConfig.ReplyToAddress,
|
||||
smtpConfig.SMTP.Host,
|
||||
smtpConfig.SMTP.User,
|
||||
[]byte(smtpConfig.SMTP.Password),
|
||||
username,
|
||||
pwd,
|
||||
smtpConfig.Tls,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
@@ -29,10 +30,11 @@ type SMTPConfig struct {
|
||||
TLS bool
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
ReplyToAddress string
|
||||
PlainAuth *instance.PlainAuth
|
||||
XOAuth2Auth *instance.XOAuth2Auth
|
||||
}
|
||||
|
||||
func NewIAMSMTPConfigWriteModel(instanceID, id, domain string) *IAMSMTPConfigWriteModel {
|
||||
@@ -85,7 +87,11 @@ func (wm *IAMSMTPConfigWriteModel) Reduce() error {
|
||||
continue
|
||||
}
|
||||
if e.Password != nil {
|
||||
wm.SMTPConfig.Password = e.Password
|
||||
if wm.SMTPConfig.PlainAuth == nil {
|
||||
wm.SMTPConfig.PlainAuth = &instance.PlainAuth{Password: e.Password}
|
||||
} else {
|
||||
wm.SMTPConfig.PlainAuth.Password = e.Password
|
||||
}
|
||||
}
|
||||
case *instance.SMTPConfigHTTPAddedEvent:
|
||||
if wm.ID != e.ID {
|
||||
@@ -157,7 +163,19 @@ func (wm *IAMSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, id, description string, tls bool, fromAddress, fromName, replyToAddress, smtpHost, smtpUser string, smtpPassword *crypto.CryptoValue) (*instance.SMTPConfigChangedEvent, bool, error) {
|
||||
func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context, aggregate *eventstore.Aggregate,
|
||||
id,
|
||||
description string,
|
||||
tls bool,
|
||||
fromAddress,
|
||||
fromName,
|
||||
replyToAddress,
|
||||
smtpHost string,
|
||||
smtpUser string,
|
||||
plainAuth *instance.PlainAuth,
|
||||
xoauth2Auth *instance.XOAuth2Auth,
|
||||
) (*instance.SMTPConfigChangedEvent, bool, error) {
|
||||
changes := make([]instance.SMTPConfigChanges, 0)
|
||||
var err error
|
||||
if wm.SMTPConfig == nil {
|
||||
@@ -188,9 +206,13 @@ func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregat
|
||||
if wm.SMTPConfig.User != smtpUser {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPUser(smtpUser))
|
||||
}
|
||||
if smtpPassword != nil {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPPassword(smtpPassword))
|
||||
if plainAuth != nil {
|
||||
changes = append(changes, smtpPlainAuthChanges(wm.SMTPConfig.PlainAuth, *plainAuth)...)
|
||||
}
|
||||
if xoauth2Auth != nil {
|
||||
changes = append(changes, smtpXOAuthChanges(wm.SMTPConfig.XOAuth2Auth, *xoauth2Auth)...)
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
@@ -201,6 +223,77 @@ func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregat
|
||||
return changeEvent, true, nil
|
||||
}
|
||||
|
||||
func smtpPlainAuthChanges(wm *instance.PlainAuth, auth instance.PlainAuth) []instance.SMTPConfigChanges {
|
||||
// if no auth is yet present, set both
|
||||
if wm == nil {
|
||||
return []instance.SMTPConfigChanges{
|
||||
instance.ChangeSMTPConfigSMTPPassword(auth.Password),
|
||||
}
|
||||
}
|
||||
|
||||
// if auth is already present, add changes for the changed values
|
||||
var changes []instance.SMTPConfigChanges
|
||||
|
||||
if auth.Password != nil {
|
||||
changes = append(changes, instance.ChangeSMTPConfigSMTPPassword(auth.Password))
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func smtpXOAuthChanges(wm *instance.XOAuth2Auth, auth instance.XOAuth2Auth) []instance.SMTPConfigChanges {
|
||||
// if no auth is yet present, set all properties
|
||||
if wm == nil {
|
||||
return []instance.SMTPConfigChanges{
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientId(auth.ClientCredentials.ClientId),
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientSecret(auth.ClientCredentials.ClientSecret),
|
||||
instance.ChangeSMTPConfigXOAuth2TokenEndpoint(auth.TokenEndpoint),
|
||||
instance.ChangeSMTPConfigXOAuth2Scopes(auth.Scopes),
|
||||
}
|
||||
}
|
||||
|
||||
// if auth is already present, add changes for the changed values
|
||||
var changes []instance.SMTPConfigChanges
|
||||
|
||||
if wm.TokenEndpoint != auth.TokenEndpoint {
|
||||
changes = append(changes, instance.ChangeSMTPConfigXOAuth2TokenEndpoint(auth.TokenEndpoint))
|
||||
}
|
||||
if len(wm.Scopes) != len(auth.Scopes) {
|
||||
changes = append(changes, instance.ChangeSMTPConfigXOAuth2Scopes(auth.Scopes))
|
||||
} else {
|
||||
for _, s := range auth.Scopes {
|
||||
if !slices.Contains(wm.Scopes, s) {
|
||||
changes = append(changes, instance.ChangeSMTPConfigXOAuth2Scopes(auth.Scopes))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if auth.ClientCredentials != nil {
|
||||
changes = append(changes, smtpXOAuthClientCredentialChanges(auth.ClientCredentials, *auth.ClientCredentials)...)
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func smtpXOAuthClientCredentialChanges(wm *instance.XOAuth2ClientCredentials, cc instance.XOAuth2ClientCredentials) []instance.SMTPConfigChanges {
|
||||
if wm == nil {
|
||||
return []instance.SMTPConfigChanges{
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientId(cc.ClientId),
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientSecret(cc.ClientSecret),
|
||||
}
|
||||
}
|
||||
|
||||
var changes []instance.SMTPConfigChanges
|
||||
if wm.ClientId != cc.ClientId {
|
||||
changes = append(changes, instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientId(cc.ClientId))
|
||||
}
|
||||
if wm.ClientSecret != cc.ClientSecret {
|
||||
changes = append(changes, instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientSecret(cc.ClientSecret))
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) NewHTTPChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
@@ -242,11 +335,30 @@ func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigAddedEvent(e *instance.SMTPCo
|
||||
TLS: e.TLS,
|
||||
Host: e.Host,
|
||||
User: e.User,
|
||||
Password: e.Password,
|
||||
SenderName: e.SenderName,
|
||||
SenderAddress: e.SenderAddress,
|
||||
ReplyToAddress: e.ReplyToAddress,
|
||||
}
|
||||
|
||||
if e.PlainAuth != nil {
|
||||
wm.SMTPConfig.PlainAuth = &instance.PlainAuth{
|
||||
Password: e.PlainAuth.Password,
|
||||
}
|
||||
}
|
||||
if e.XOAuth2Auth != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth = &instance.XOAuth2Auth{
|
||||
TokenEndpoint: e.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: e.XOAuth2Auth.Scopes,
|
||||
}
|
||||
|
||||
if e.XOAuth2Auth.ClientCredentials != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth.ClientCredentials = &instance.XOAuth2ClientCredentials{
|
||||
ClientId: e.XOAuth2Auth.ClientCredentials.ClientId,
|
||||
ClientSecret: e.XOAuth2Auth.ClientCredentials.ClientSecret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wm.State = domain.SMTPConfigStateInactive
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
@@ -290,9 +402,6 @@ func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigChangedEvent(e *instance.SMTP
|
||||
if e.User != nil {
|
||||
wm.SMTPConfig.User = *e.User
|
||||
}
|
||||
if e.Password != nil {
|
||||
wm.SMTPConfig.Password = e.Password
|
||||
}
|
||||
if e.FromAddress != nil {
|
||||
wm.SMTPConfig.SenderAddress = *e.FromAddress
|
||||
}
|
||||
@@ -303,6 +412,39 @@ func (wm *IAMSMTPConfigWriteModel) reduceSMTPConfigChangedEvent(e *instance.SMTP
|
||||
wm.SMTPConfig.ReplyToAddress = *e.ReplyToAddress
|
||||
}
|
||||
|
||||
if !e.PlainAuth.IsEmpty() {
|
||||
if wm.SMTPConfig.PlainAuth == nil {
|
||||
wm.SMTPConfig.PlainAuth = &instance.PlainAuth{}
|
||||
wm.SMTPConfig.XOAuth2Auth = nil
|
||||
}
|
||||
if e.PlainAuth.Password != nil {
|
||||
wm.SMTPConfig.PlainAuth.Password = e.PlainAuth.Password
|
||||
} else if e.Password != nil {
|
||||
wm.SMTPConfig.PlainAuth.Password = e.Password
|
||||
}
|
||||
}
|
||||
|
||||
if !e.XOAuth2Auth.IsEmpty() {
|
||||
if wm.SMTPConfig.XOAuth2Auth == nil {
|
||||
wm.SMTPConfig.XOAuth2Auth = &instance.XOAuth2Auth{}
|
||||
wm.SMTPConfig.PlainAuth = nil
|
||||
}
|
||||
if e.XOAuth2Auth.TokenEndpoint != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth.TokenEndpoint = *e.XOAuth2Auth.TokenEndpoint
|
||||
}
|
||||
if e.XOAuth2Auth.Scopes != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth.Scopes = e.XOAuth2Auth.Scopes
|
||||
}
|
||||
if wm.SMTPConfig.XOAuth2Auth.ClientCredentials != nil && !e.XOAuth2Auth.ClientCredentials.IsEmpty() {
|
||||
if e.XOAuth2Auth.ClientCredentials.ClientId != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth.ClientCredentials.ClientId = *e.XOAuth2Auth.ClientCredentials.ClientId
|
||||
}
|
||||
if e.XOAuth2Auth.ClientCredentials.ClientSecret != nil {
|
||||
wm.SMTPConfig.XOAuth2Auth.ClientCredentials.ClientSecret = e.XOAuth2Auth.ClientCredentials.ClientSecret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If ID has empty value we're dealing with the old and unique smtp settings
|
||||
// These would be the default values for ID and State
|
||||
if e.ID == "" {
|
||||
|
||||
+140
-36
@@ -23,11 +23,25 @@ type AddSMTPConfig struct {
|
||||
Description string
|
||||
Host string
|
||||
User string
|
||||
Password string
|
||||
Tls bool
|
||||
From string
|
||||
FromName string
|
||||
ReplyToAddress string
|
||||
PlainAuth *PlainAuth
|
||||
XOAuth2Auth *XOAuth2Auth
|
||||
}
|
||||
|
||||
type PlainAuth struct {
|
||||
Password string
|
||||
}
|
||||
type XOAuth2Auth struct {
|
||||
TokenEndpoint string
|
||||
Scopes []string
|
||||
ClientCredentialsAuth *OAuth2ClientCredentials
|
||||
}
|
||||
type OAuth2ClientCredentials struct {
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, config *AddSMTPConfig) (err error) {
|
||||
@@ -55,14 +69,6 @@ func (c *Commands) AddSMTPConfig(ctx context.Context, config *AddSMTPConfig) (er
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-EvAtufIinh", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
if config.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, senderDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -73,6 +79,36 @@ func (c *Commands) AddSMTPConfig(ctx context.Context, config *AddSMTPConfig) (er
|
||||
return err
|
||||
}
|
||||
|
||||
var plainAuth *instance.PlainAuth
|
||||
var xoauth2Auth *instance.XOAuth2Auth
|
||||
|
||||
if config.XOAuth2Auth != nil {
|
||||
xoauth2Auth = &instance.XOAuth2Auth{
|
||||
TokenEndpoint: config.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: config.XOAuth2Auth.Scopes,
|
||||
}
|
||||
|
||||
if config.XOAuth2Auth.ClientCredentialsAuth != nil {
|
||||
clientSecret, err := crypto.Encrypt([]byte(config.XOAuth2Auth.ClientCredentialsAuth.ClientSecret), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
xoauth2Auth.ClientCredentials = &instance.XOAuth2ClientCredentials{
|
||||
ClientId: config.XOAuth2Auth.ClientCredentialsAuth.ClientId,
|
||||
ClientSecret: clientSecret,
|
||||
}
|
||||
}
|
||||
}
|
||||
if config.PlainAuth != nil {
|
||||
plainAuth = &instance.PlainAuth{}
|
||||
if config.PlainAuth.Password != "" {
|
||||
plainAuth.Password, err = crypto.Encrypt([]byte(config.PlainAuth.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = c.pushAppendAndReduce(ctx,
|
||||
smtpConfigWriteModel,
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
@@ -86,12 +122,14 @@ func (c *Commands) AddSMTPConfig(ctx context.Context, config *AddSMTPConfig) (er
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.User,
|
||||
smtpPassword,
|
||||
plainAuth,
|
||||
xoauth2Auth,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Details = writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel)
|
||||
return nil
|
||||
}
|
||||
@@ -104,11 +142,12 @@ type ChangeSMTPConfig struct {
|
||||
Description string
|
||||
Host string
|
||||
User string
|
||||
Password string
|
||||
Tls bool
|
||||
From string
|
||||
FromName string
|
||||
ReplyToAddress string
|
||||
PlainAuth *PlainAuth
|
||||
XOAuth2Auth *XOAuth2Auth
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *ChangeSMTPConfig) error {
|
||||
@@ -132,15 +171,6 @@ func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *ChangeSMTPConfi
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-kZNVkuL32L", "Errors.Invalid.Argument")
|
||||
}
|
||||
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
var err error
|
||||
if config.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, config.ResourceOwner, config.ID, senderDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -155,6 +185,35 @@ func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *ChangeSMTPConfi
|
||||
return err
|
||||
}
|
||||
|
||||
var plainAuth *instance.PlainAuth
|
||||
var xoauth2Auth *instance.XOAuth2Auth
|
||||
|
||||
if config.PlainAuth != nil {
|
||||
plainAuth = &instance.PlainAuth{}
|
||||
if config.PlainAuth.Password != "" {
|
||||
plainAuth.Password, err = crypto.Encrypt([]byte(config.PlainAuth.Password), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if config.XOAuth2Auth != nil {
|
||||
xoauth2Auth = &instance.XOAuth2Auth{
|
||||
TokenEndpoint: config.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: config.XOAuth2Auth.Scopes,
|
||||
}
|
||||
if config.XOAuth2Auth.ClientCredentialsAuth != nil {
|
||||
xoauth2Auth.ClientCredentials = &instance.XOAuth2ClientCredentials{
|
||||
ClientId: config.XOAuth2Auth.ClientCredentialsAuth.ClientId,
|
||||
}
|
||||
if config.XOAuth2Auth.ClientCredentialsAuth.ClientSecret != "" {
|
||||
xoauth2Auth.ClientCredentials.ClientSecret, err = crypto.Encrypt([]byte(config.XOAuth2Auth.ClientCredentialsAuth.ClientSecret), c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changedEvent, hasChanged, err := smtpConfigWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
InstanceAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel),
|
||||
@@ -166,7 +225,8 @@ func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *ChangeSMTPConfi
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
config.User,
|
||||
smtpPassword,
|
||||
plainAuth,
|
||||
xoauth2Auth,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -430,34 +490,50 @@ func (c *Commands) RemoveSMTPConfig(ctx context.Context, resourceOwner, id strin
|
||||
}
|
||||
|
||||
func (c *Commands) TestSMTPConfig(ctx context.Context, instanceID, id, email string, config *smtp.Config) error {
|
||||
password := config.SMTP.Password
|
||||
|
||||
if email == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9uy", "Errors.SMTPConfig.TestEmailNotFound")
|
||||
}
|
||||
|
||||
if id == "" && password == "" {
|
||||
if id == "" && config.SMTP.PlainAuth != nil && config.SMTP.PlainAuth.Password == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9kj", "Errors.SMTPConfig.TestPassword")
|
||||
}
|
||||
|
||||
// If the password is not sent it'd mean that the password hasn't been changed for
|
||||
// the stored configuration identified by its id so we can try to retrieve it
|
||||
if id != "" && password == "" {
|
||||
if id == "" && config.SMTP.XOAuth2Auth != nil &&
|
||||
config.SMTP.XOAuth2Auth.ClientCredentialsAuth != nil &&
|
||||
config.SMTP.XOAuth2Auth.ClientCredentialsAuth.ClientSecret == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "SMTP-9OP96s", "Errors.SMTPConfig.TestClientSecret")
|
||||
}
|
||||
|
||||
if config.SMTP.PlainAuth != nil && config.SMTP.PlainAuth.Password == "" {
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.SMTPConfig == nil {
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.SMTPConfig == nil || smtpConfigWriteModel.SMTPConfig.PlainAuth == nil {
|
||||
return zerrors.ThrowNotFound(nil, "SMTP-p9cc", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
password, err = crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.Password, c.smtpEncryption)
|
||||
config.SMTP.PlainAuth.Password, err = crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.PlainAuth.Password, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
config.SMTP.Password = password
|
||||
if config.SMTP.XOAuth2Auth != nil && config.SMTP.XOAuth2Auth.ClientCredentialsAuth != nil && config.SMTP.XOAuth2Auth.ClientCredentialsAuth.ClientSecret == "" {
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !smtpConfigWriteModel.State.Exists() || smtpConfigWriteModel.SMTPConfig == nil || smtpConfigWriteModel.SMTPConfig.XOAuth2Auth == nil {
|
||||
return zerrors.ThrowNotFound(nil, "SMTP-p9c2", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
config.SMTP.XOAuth2Auth.ClientCredentialsAuth.ClientSecret, err = crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.ClientCredentials.ClientSecret, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Try to send an email
|
||||
err := smtp.TestConfiguration(config, email)
|
||||
@@ -486,9 +562,36 @@ func (c *Commands) TestSMTPConfigById(ctx context.Context, instanceID, id, email
|
||||
return zerrors.ThrowNotFound(nil, "SMTP-99klw", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
password, err := crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.Password, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
var plainAuth *smtp.PlainAuthConfig
|
||||
var xoauth2Auth *smtp.XOAuth2AuthConfig
|
||||
|
||||
if smtpConfigWriteModel.SMTPConfig.PlainAuth != nil {
|
||||
password, err := crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.PlainAuth.Password, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
plainAuth = &smtp.PlainAuthConfig{
|
||||
User: smtpConfigWriteModel.SMTPConfig.User,
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
|
||||
if smtpConfigWriteModel.SMTPConfig.XOAuth2Auth != nil {
|
||||
xoauth2Auth = &smtp.XOAuth2AuthConfig{
|
||||
User: smtpConfigWriteModel.SMTPConfig.User,
|
||||
TokenEndpoint: smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.Scopes,
|
||||
}
|
||||
if smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.ClientCredentials != nil {
|
||||
clientSecret, err := crypto.DecryptString(smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.ClientCredentials.ClientSecret, c.smtpEncryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
xoauth2Auth.ClientCredentialsAuth = &smtp.OAuth2ClientCredentials{
|
||||
ClientId: smtpConfigWriteModel.SMTPConfig.XOAuth2Auth.ClientCredentials.ClientId,
|
||||
ClientSecret: clientSecret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smtpConfig := &smtp.Config{
|
||||
@@ -496,9 +599,9 @@ func (c *Commands) TestSMTPConfigById(ctx context.Context, instanceID, id, email
|
||||
From: smtpConfigWriteModel.SMTPConfig.SenderAddress,
|
||||
FromName: smtpConfigWriteModel.SMTPConfig.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: smtpConfigWriteModel.SMTPConfig.Host,
|
||||
User: smtpConfigWriteModel.SMTPConfig.User,
|
||||
Password: password,
|
||||
Host: smtpConfigWriteModel.SMTPConfig.Host,
|
||||
PlainAuth: plainAuth,
|
||||
XOAuth2Auth: xoauth2Auth,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -582,7 +685,8 @@ func (c *Commands) prepareAddAndActivateSMTPConfig(a *instance.Aggregate, descri
|
||||
replyTo,
|
||||
hostAndPort,
|
||||
user,
|
||||
smtpPassword,
|
||||
&instance.PlainAuth{Password: smtpPassword},
|
||||
nil,
|
||||
),
|
||||
instance.NewSMTPConfigActivatedEvent(
|
||||
ctx,
|
||||
|
||||
+674
-59
@@ -78,7 +78,9 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
From: "[email protected]",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -136,12 +138,15 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -157,7 +162,9 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -197,12 +204,15 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
"[email protected]",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -219,7 +229,9 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -244,7 +256,9 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -269,7 +283,9 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: " ",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -309,12 +325,15 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"[2001:db8::1]:2525",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -330,7 +349,200 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "[2001:db8::1]:2525",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add smtp config with plain auth but no password, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"[email protected]",
|
||||
"name",
|
||||
"[email protected]",
|
||||
"host:587",
|
||||
"user",
|
||||
&instance.PlainAuth{},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
smtp: &AddSMTPConfig{
|
||||
ResourceOwner: "INSTANCE",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "[email protected]",
|
||||
FromName: "name",
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add smtp config without auth, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"[email protected]",
|
||||
"name",
|
||||
"[email protected]",
|
||||
"host:587",
|
||||
"",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
smtp: &AddSMTPConfig{
|
||||
ResourceOwner: "INSTANCE",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "[email protected]",
|
||||
FromName: "name",
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host:587",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add smtp config with xoauth2 auth, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"configid",
|
||||
"test",
|
||||
true,
|
||||
"[email protected]",
|
||||
"name",
|
||||
"[email protected]",
|
||||
"host:587",
|
||||
"user",
|
||||
nil,
|
||||
&instance.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentials: &instance.XOAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "configid"),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
smtp: &AddSMTPConfig{
|
||||
ResourceOwner: "INSTANCE",
|
||||
Description: "test",
|
||||
Tls: true,
|
||||
From: "[email protected]",
|
||||
FromName: "name",
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
XOAuth2Auth: &XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentialsAuth: &OAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -365,6 +577,7 @@ func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
smtp *ChangeSMTPConfig
|
||||
@@ -443,6 +656,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -481,7 +695,10 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -497,6 +714,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -533,7 +751,10 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -549,6 +770,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host:587",
|
||||
User: "user",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -587,7 +809,10 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -602,6 +827,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"[email protected]",
|
||||
"host2:587",
|
||||
"user2",
|
||||
&instance.PlainAuth{},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -617,6 +844,7 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host2:587",
|
||||
User: "user2",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -640,7 +868,9 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -664,7 +894,9 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
FromName: "name",
|
||||
Host: " ",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -703,7 +935,10 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -718,6 +953,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
"[email protected]",
|
||||
"[2001:db8::1]:2525",
|
||||
"user2",
|
||||
&instance.PlainAuth{},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -733,6 +970,193 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "[2001:db8::1]:2525",
|
||||
User: "user2",
|
||||
PlainAuth: &PlainAuth{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change auth from plain to xoauth2, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"",
|
||||
true,
|
||||
"[email protected]",
|
||||
"name",
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&instance.PlainAuth{},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newSMTPConfigChangedEvent(
|
||||
context.Background(),
|
||||
"ID",
|
||||
"test",
|
||||
false,
|
||||
"[email protected]",
|
||||
"name2",
|
||||
"[email protected]",
|
||||
"host2:587",
|
||||
"user2",
|
||||
nil,
|
||||
&instance.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentials: &instance.XOAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
smtp: &ChangeSMTPConfig{
|
||||
ResourceOwner: "INSTANCE",
|
||||
ID: "ID",
|
||||
Description: "test",
|
||||
Tls: false,
|
||||
From: "[email protected]",
|
||||
FromName: "name2",
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host2:587",
|
||||
User: "user2",
|
||||
XOAuth2Auth: &XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentialsAuth: &OAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change auth from xoauth2 to plain, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"domain.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true, true, true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"",
|
||||
true,
|
||||
"[email protected]",
|
||||
"name",
|
||||
"",
|
||||
"host:587",
|
||||
"user2",
|
||||
nil,
|
||||
&instance.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentials: &instance.XOAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("client-secret"),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newSMTPConfigChangedEvent(
|
||||
context.Background(),
|
||||
"ID",
|
||||
"test",
|
||||
false,
|
||||
"[email protected]",
|
||||
"name2",
|
||||
"[email protected]",
|
||||
"host2:587",
|
||||
"user",
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
smtp: &ChangeSMTPConfig{
|
||||
ResourceOwner: "INSTANCE",
|
||||
ID: "ID",
|
||||
Description: "test",
|
||||
Tls: false,
|
||||
From: "[email protected]",
|
||||
FromName: "name2",
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "host2:587",
|
||||
User: "user",
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -745,7 +1169,8 @@ func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
smtpEncryption: tt.fields.alg,
|
||||
}
|
||||
err := r.ChangeSMTPConfig(context.Background(), tt.args.smtp)
|
||||
if tt.res.err == nil {
|
||||
@@ -842,7 +1267,10 @@ func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -1261,7 +1689,10 @@ func TestCommandSide_ActivateSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1302,7 +1733,10 @@ func TestCommandSide_ActivateSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -1466,7 +1900,10 @@ func TestCommandSide_DeactivateSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -1513,7 +1950,10 @@ func TestCommandSide_DeactivateSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
@@ -1692,7 +2132,10 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"host:587",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1837,9 +2280,11 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
From: "test@example,com",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
User: "user",
|
||||
Password: "",
|
||||
Host: "example.com:2525",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "",
|
||||
},
|
||||
Host: "example.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1863,9 +2308,11 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
From: "test@example,com",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
User: "user",
|
||||
Password: "",
|
||||
Host: "example.com:2525",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "",
|
||||
},
|
||||
Host: "example.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1874,7 +2321,7 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid new smtp config, wrong auth, ok",
|
||||
name: "valid new smtp config, wrong plain auth, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
@@ -1887,9 +2334,11 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
From: "[email protected]",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1914,11 +2363,103 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
"",
|
||||
"mail.smtp2go.com:2525",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
instanceID: "INSTANCE",
|
||||
email: "email",
|
||||
id: "ID",
|
||||
config: smtp.Config{
|
||||
From: "[email protected]",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "",
|
||||
},
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsInternal,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid new smtp config, wrong xoauth2 auth, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
instanceID: "INSTANCE",
|
||||
email: "email",
|
||||
config: smtp.Config{
|
||||
From: "[email protected]",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
XOAuth2Auth: &smtp.XOAuth2AuthConfig{
|
||||
User: "user",
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentialsAuth: &smtp.OAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: "client-secret",
|
||||
},
|
||||
},
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsInternal,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid smtp config using stored password, wrong auth, ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"",
|
||||
"mail.smtp2go.com:2525",
|
||||
"user",
|
||||
nil,
|
||||
&instance.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentials: &instance.XOAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -1935,9 +2476,15 @@ func TestCommandSide_TestSMTPConfig(t *testing.T) {
|
||||
From: "[email protected]",
|
||||
FromName: "Test",
|
||||
SMTP: smtp.SMTP{
|
||||
User: "user",
|
||||
Password: "",
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
XOAuth2Auth: &smtp.XOAuth2AuthConfig{
|
||||
User: "user",
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentialsAuth: &smtp.OAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
},
|
||||
},
|
||||
Host: "mail.smtp2go.com:2525",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2032,7 +2579,7 @@ func TestCommandSide_TestSMTPConfigById(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid smtp config, wrong auth, ok",
|
||||
name: "valid smtp config, wrong plain auth, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
@@ -2049,11 +2596,62 @@ func TestCommandSide_TestSMTPConfigById(t *testing.T) {
|
||||
"",
|
||||
"mail.smtp2go.com:2525",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
&instance.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
id: "ID",
|
||||
instanceID: "INSTANCE",
|
||||
email: "[email protected]",
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsInternal,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid smtp config, wrong xoauth2 auth, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
"ID",
|
||||
"test",
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"",
|
||||
"mail.smtp2go.com:2525",
|
||||
"user",
|
||||
nil,
|
||||
&instance.XOAuth2Auth{
|
||||
TokenEndpoint: "auth.example.com/token",
|
||||
Scopes: []string{"scope"},
|
||||
ClientCredentials: &instance.XOAuth2ClientCredentials{
|
||||
ClientId: "client-id",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("client-secret"),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -2089,7 +2687,7 @@ func TestCommandSide_TestSMTPConfigById(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls bool, fromAddress, fromName, replyTo, host, user string) *instance.SMTPConfigChangedEvent {
|
||||
func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls bool, fromAddress, fromName, replyTo, host, user string, plainAuth *instance.PlainAuth, xoauth2Auth *instance.XOAuth2Auth) *instance.SMTPConfigChangedEvent {
|
||||
changes := []instance.SMTPConfigChanges{
|
||||
instance.ChangeSMTPConfigDescription(description),
|
||||
instance.ChangeSMTPConfigTLS(tls),
|
||||
@@ -2099,6 +2697,23 @@ func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls
|
||||
instance.ChangeSMTPConfigSMTPHost(host),
|
||||
instance.ChangeSMTPConfigSMTPUser(user),
|
||||
}
|
||||
if plainAuth != nil {
|
||||
changes = append(changes,
|
||||
instance.ChangeSMTPConfigSMTPPassword(plainAuth.Password),
|
||||
)
|
||||
}
|
||||
if xoauth2Auth != nil {
|
||||
changes = append(changes,
|
||||
instance.ChangeSMTPConfigXOAuth2TokenEndpoint(xoauth2Auth.TokenEndpoint),
|
||||
instance.ChangeSMTPConfigXOAuth2Scopes(xoauth2Auth.Scopes),
|
||||
)
|
||||
if xoauth2Auth.ClientCredentials != nil {
|
||||
changes = append(changes,
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientId(xoauth2Auth.ClientCredentials.ClientId),
|
||||
instance.ChangeSMTPConfigXOAuth2ClientCredentialsClientSecret(xoauth2Auth.ClientCredentials.ClientSecret),
|
||||
)
|
||||
}
|
||||
}
|
||||
event, _ := instance.NewSMTPConfigChangeEvent(ctx,
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
id,
|
||||
|
||||
@@ -31,20 +31,33 @@ func EnsureInstanceFeature(t *testing.T, ctx context.Context, instance *Instance
|
||||
}
|
||||
|
||||
type RelationalTableFeatureMatrix struct {
|
||||
State string
|
||||
FeatureSet *feature.SetInstanceFeaturesRequest
|
||||
Name string
|
||||
Inst *Instance
|
||||
InstOwner context.Context
|
||||
}
|
||||
|
||||
// TODO(IAM-Marco): Once we have gotten rid of eventstore, this can be removed
|
||||
func RelationalTablesEnableMatrix() []RelationalTableFeatureMatrix {
|
||||
func RelationalTablesEnableMatrix(t *testing.T, ctx context.Context, sysAuthZ context.Context) []RelationalTableFeatureMatrix {
|
||||
return []RelationalTableFeatureMatrix{
|
||||
{
|
||||
State: "when relational tables are disabled",
|
||||
FeatureSet: &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(false)},
|
||||
},
|
||||
{
|
||||
State: "when relational tables are enabled",
|
||||
FeatureSet: &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(true)},
|
||||
},
|
||||
func() RelationalTableFeatureMatrix {
|
||||
inst := NewInstance(sysAuthZ)
|
||||
instOwner := inst.WithAuthorizationToken(ctx, UserTypeIAMOwner)
|
||||
return RelationalTableFeatureMatrix{
|
||||
Name: "when relational tables are disabled",
|
||||
Inst: inst,
|
||||
InstOwner: instOwner,
|
||||
}
|
||||
}(),
|
||||
func() RelationalTableFeatureMatrix {
|
||||
inst := NewInstance(sysAuthZ)
|
||||
instOwner := inst.WithAuthorizationToken(ctx, UserTypeIAMOwner)
|
||||
_, err := inst.Client.FeatureV2.SetInstanceFeatures(instOwner, &feature.SetInstanceFeaturesRequest{EnableRelationalTables: gu.Ptr(false)})
|
||||
require.NoError(t, err)
|
||||
return RelationalTableFeatureMatrix{
|
||||
Name: "when relational tables are enabled",
|
||||
Inst: inst,
|
||||
InstOwner: instOwner,
|
||||
}
|
||||
}(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,14 +148,22 @@ func (smtpConfig SMTP) getSMTPClientWithStartTls(host string) (*smtp.Client, err
|
||||
}
|
||||
|
||||
func (smtpConfig SMTP) smtpAuth(client *smtp.Client, host string) error {
|
||||
if !smtpConfig.HasAuth() {
|
||||
if smtpConfig.XOAuth2Auth != nil {
|
||||
err := client.Auth(XOAuth2Auth(*smtpConfig.XOAuth2Auth, host))
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "EMAIL-av88SB", "Errors.SMTP.CouldNotXOAuth2")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Auth
|
||||
err := client.Auth(PlainOrLoginAuth(smtpConfig.User, smtpConfig.Password, host))
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s9kfs", "Errors.SMTP.CouldNotAuth")
|
||||
|
||||
if smtpConfig.PlainAuth != nil {
|
||||
err := client.Auth(PlainOrLoginAuth(*smtpConfig.PlainAuth, host))
|
||||
if err != nil {
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s9kfs", "Errors.SMTP.CouldNotAuth")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -176,11 +184,11 @@ func TestConfiguration(cfg *Config, testEmail string) error {
|
||||
}
|
||||
|
||||
if err := client.Mail(cfg.From); err != nil {
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s3is3", "Errors.SMTP.CouldNotSetSender")
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s5is5", "Errors.SMTP.CouldNotSetSender")
|
||||
}
|
||||
|
||||
if err := client.Rcpt(testEmail); err != nil {
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s4is4", "Errors.SMTP.CouldNotSetRecipient")
|
||||
return zerrors.ThrowInternal(err, "EMAIL-s6is6", "Errors.SMTP.CouldNotSetRecipient")
|
||||
}
|
||||
|
||||
// Open data connection
|
||||
|
||||
@@ -9,19 +9,9 @@ type Config struct {
|
||||
}
|
||||
|
||||
type SMTP struct {
|
||||
Host string
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
|
||||
// HasAuth reports whether SMTP authentication should be attempted.
|
||||
//
|
||||
// It returns true when a User is configured, regardless of whether Password
|
||||
// is set. This behavior is intentional to support SMTP servers that allow
|
||||
// authentication without a password. For servers that require a password,
|
||||
// this means authentication may still be attempted with an empty password.
|
||||
func (smtp *SMTP) HasAuth() bool {
|
||||
return smtp.User != ""
|
||||
Host string
|
||||
PlainAuth *PlainAuthConfig
|
||||
XOAuth2Auth *XOAuth2AuthConfig
|
||||
}
|
||||
|
||||
type ConfigHTTP struct {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"net/smtp"
|
||||
"slices"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
type GenericAuth struct {
|
||||
Host string
|
||||
PlainOrLogin *plainOrLoginAuth
|
||||
XOAuth2 *xoauth2Auth
|
||||
selectedMethod smtp.Auth
|
||||
}
|
||||
|
||||
func (a *GenericAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
|
||||
if server.Name != a.Host {
|
||||
return "", nil, zerrors.ThrowInternal(nil, "SMTP-BtXgkX", "wrong host name")
|
||||
}
|
||||
|
||||
switch {
|
||||
case slices.Contains(server.Auth, "XOAUTH2") && a.XOAuth2 != nil:
|
||||
a.selectedMethod = a.XOAuth2
|
||||
case slices.Contains(server.Auth, "PLAIN") && a.PlainOrLogin != nil:
|
||||
a.selectedMethod = a.PlainOrLogin
|
||||
case slices.Contains(server.Auth, "LOGIN") && a.PlainOrLogin != nil:
|
||||
a.selectedMethod = a.PlainOrLogin
|
||||
default:
|
||||
return "", nil, zerrors.ThrowInternalf(nil, "SMTP-3mBHTz", "no supported auth method found (server supports: %v)", server.Auth)
|
||||
}
|
||||
return a.selectedMethod.Start(server)
|
||||
}
|
||||
|
||||
func (a *GenericAuth) Next(fromServer []byte, more bool) ([]byte, error) {
|
||||
if a.selectedMethod == nil {
|
||||
return nil, zerrors.ThrowInternal(nil, "SMTP-G99DUr", "no auth method selected")
|
||||
}
|
||||
|
||||
return a.selectedMethod.Next(fromServer, more)
|
||||
}
|
||||
@@ -11,17 +11,24 @@ import (
|
||||
// golang net/smtp SMTP AUTH LOGIN or PLAIN Auth Handler
|
||||
// Reference: https://gist.github.com/andelf/5118732?permalink_comment_id=4825669#gistcomment-4825669
|
||||
|
||||
func PlainOrLoginAuth(username, password, host string) smtp.Auth {
|
||||
return &plainOrLoginAuth{username: username, password: password, host: host}
|
||||
func PlainOrLoginAuth(config PlainAuthConfig, host string) smtp.Auth {
|
||||
return &plainOrLoginAuth{
|
||||
host: host,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
type plainOrLoginAuth struct {
|
||||
username string
|
||||
password string
|
||||
host string
|
||||
config PlainAuthConfig
|
||||
authMethod string
|
||||
}
|
||||
|
||||
type PlainAuthConfig struct {
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
|
||||
func (a *plainOrLoginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
|
||||
if server.Name != a.host {
|
||||
return "", nil, zerrors.ThrowInternal(nil, "SMTP-RRi75", "wrong host name")
|
||||
@@ -31,7 +38,7 @@ func (a *plainOrLoginAuth) Start(server *smtp.ServerInfo) (string, []byte, error
|
||||
return a.authMethod, nil, nil
|
||||
} else {
|
||||
a.authMethod = "PLAIN"
|
||||
resp := []byte("\x00" + a.username + "\x00" + a.password)
|
||||
resp := []byte("\x00" + a.config.User + "\x00" + a.config.Password)
|
||||
return a.authMethod, resp, nil
|
||||
}
|
||||
}
|
||||
@@ -48,9 +55,9 @@ func (a *plainOrLoginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
|
||||
|
||||
switch {
|
||||
case bytes.Equal(fromServer, []byte("Username:")):
|
||||
return []byte(a.username), nil
|
||||
return []byte(a.config.User), nil
|
||||
case bytes.Equal(fromServer, []byte("Password:")):
|
||||
return []byte(a.password), nil
|
||||
return []byte(a.config.Password), nil
|
||||
default:
|
||||
return nil, zerrors.ThrowInternal(nil, "SMTP-HjW21", "unexpected server challenge")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hash/fnv"
|
||||
"net/smtp"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/clientcredentials"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
var tokenSourceCache *lru.TwoQueueCache[string, oauth2.TokenSource]
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
tokenSourceCache, err = lru.New2Q[string, oauth2.TokenSource](100)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type XOAuth2AuthConfig struct {
|
||||
User string
|
||||
TokenEndpoint string
|
||||
Scopes []string
|
||||
ClientCredentialsAuth *OAuth2ClientCredentials
|
||||
}
|
||||
|
||||
type OAuth2ClientCredentials struct {
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
func (cfg XOAuth2AuthConfig) Hash() string {
|
||||
hash := fnv.New128()
|
||||
hash.Write([]byte(cfg.User))
|
||||
hash.Write([]byte(cfg.TokenEndpoint))
|
||||
for _, s := range cfg.Scopes {
|
||||
hash.Write([]byte(s))
|
||||
}
|
||||
if cfg.ClientCredentialsAuth != nil {
|
||||
hash.Write([]byte(cfg.ClientCredentialsAuth.ClientId))
|
||||
hash.Write([]byte(cfg.ClientCredentialsAuth.ClientSecret))
|
||||
}
|
||||
return string(hash.Sum(nil))
|
||||
}
|
||||
|
||||
type xoauth2Auth struct {
|
||||
host string
|
||||
config XOAuth2AuthConfig
|
||||
}
|
||||
|
||||
func XOAuth2Auth(config XOAuth2AuthConfig, host string) smtp.Auth {
|
||||
return &xoauth2Auth{
|
||||
host: host,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
func (a *xoauth2Auth) Start(server *smtp.ServerInfo) (string, []byte, error) {
|
||||
if server.Name != a.host {
|
||||
return "", nil, zerrors.ThrowInternal(nil, "SMTP-eRJLyi", "wrong host name")
|
||||
}
|
||||
|
||||
hash := a.config.Hash()
|
||||
tokenSource, ok := tokenSourceCache.Get(hash)
|
||||
if !ok {
|
||||
if a.config.ClientCredentialsAuth != nil {
|
||||
config := &clientcredentials.Config{
|
||||
ClientID: a.config.ClientCredentialsAuth.ClientId,
|
||||
ClientSecret: a.config.ClientCredentialsAuth.ClientSecret,
|
||||
Scopes: a.config.Scopes,
|
||||
TokenURL: a.config.TokenEndpoint,
|
||||
}
|
||||
tokenSource = config.TokenSource(context.Background())
|
||||
tokenSourceCache.Add(hash, tokenSource)
|
||||
}
|
||||
}
|
||||
|
||||
token, err := tokenSource.Token()
|
||||
if err != nil {
|
||||
return "", nil, zerrors.ThrowInternal(err, "SMTP-fjHcJu", "Failed to get token to connect with smtp server")
|
||||
}
|
||||
|
||||
resp := []byte("user=" + a.config.User + "\x01" + "auth=Bearer " + token.AccessToken + "\x01\x01")
|
||||
return "XOAUTH2", resp, nil
|
||||
}
|
||||
|
||||
func (a *xoauth2Auth) Next(_ []byte, more bool) ([]byte, error) {
|
||||
if !more {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, zerrors.ThrowInternal(nil, "SMTP-Pqsrj9", "unexpected server challenge for XOAUTH2 auth method")
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/email"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/zitadel/zitadel/internal/notification/channels/webhook"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@@ -22,30 +23,11 @@ func (n *NotificationQueries) GetActiveEmailConfig(ctx context.Context) (*email.
|
||||
ID: config.ID,
|
||||
Description: config.Description,
|
||||
}
|
||||
if config.SMTPConfig != nil {
|
||||
var password string
|
||||
if config.SMTPConfig.Password != nil {
|
||||
password, err = crypto.DecryptString(config.SMTPConfig.Password, n.SMTPPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &email.Config{
|
||||
ProviderConfig: provider,
|
||||
SMTPConfig: &smtp.Config{
|
||||
From: config.SMTPConfig.SenderAddress,
|
||||
FromName: config.SMTPConfig.SenderName,
|
||||
ReplyToAddress: config.SMTPConfig.ReplyToAddress,
|
||||
Tls: config.SMTPConfig.TLS,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: config.SMTPConfig.Host,
|
||||
User: config.SMTPConfig.User,
|
||||
Password: password,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
if config.SMTPConfig != nil {
|
||||
return smtpToEmailConfig(config.SMTPConfig, provider, n.SMTPPasswordCrypto)
|
||||
}
|
||||
|
||||
if config.HTTPConfig != nil {
|
||||
return &email.Config{
|
||||
ProviderConfig: provider,
|
||||
@@ -59,3 +41,61 @@ func (n *NotificationQueries) GetActiveEmailConfig(ctx context.Context) (*email.
|
||||
}
|
||||
return nil, zerrors.ThrowNotFound(err, "QUERY-KPQleOckOV", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
|
||||
func smtpToEmailConfig(qs *query.SMTP, provider *email.Provider, passCrypto crypto.EncryptionAlgorithm) (*email.Config, error) {
|
||||
config := &email.Config{
|
||||
ProviderConfig: provider,
|
||||
SMTPConfig: &smtp.Config{
|
||||
From: qs.SenderAddress,
|
||||
FromName: qs.SenderName,
|
||||
ReplyToAddress: qs.ReplyToAddress,
|
||||
Tls: qs.TLS,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: qs.Host,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if qs.XOAuth2Auth != nil {
|
||||
config.SMTPConfig.SMTP.XOAuth2Auth = &smtp.XOAuth2AuthConfig{
|
||||
User: qs.User,
|
||||
TokenEndpoint: qs.XOAuth2Auth.TokenEndpoint,
|
||||
Scopes: qs.XOAuth2Auth.Scopes,
|
||||
}
|
||||
if qs.XOAuth2Auth.ClientCredentials != nil {
|
||||
clientSecret, err := crypto.DecryptString(qs.XOAuth2Auth.ClientCredentials.ClientSecret, passCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SMTPConfig.SMTP.XOAuth2Auth.ClientCredentialsAuth = &smtp.OAuth2ClientCredentials{
|
||||
ClientId: qs.XOAuth2Auth.ClientCredentials.ClientId,
|
||||
ClientSecret: clientSecret,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if qs.PlainAuth != nil {
|
||||
config.SMTPConfig.SMTP.PlainAuth = &smtp.PlainAuthConfig{
|
||||
User: qs.User,
|
||||
}
|
||||
|
||||
if qs.PlainAuth.Password != nil {
|
||||
password, err := crypto.DecryptString(qs.PlainAuth.Password, passCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.SMTPConfig.SMTP.PlainAuth.Password = password
|
||||
}
|
||||
}
|
||||
|
||||
// if no auth is configured but there is a user, use plain auth without a password
|
||||
if qs.User != "" &&
|
||||
config.SMTPConfig.SMTP.PlainAuth == nil &&
|
||||
config.SMTPConfig.SMTP.XOAuth2Auth == nil {
|
||||
config.SMTPConfig.SMTP.PlainAuth = &smtp.PlainAuthConfig{
|
||||
User: qs.User,
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -45,11 +45,13 @@ func TestNotificationQueries_GetActiveEmailConfig(t *testing.T) {
|
||||
ReplyToAddress: "[email protected]",
|
||||
Host: "mail.com",
|
||||
User: "mail-user",
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: 0,
|
||||
Algorithm: cryptAlg,
|
||||
KeyID: keyId,
|
||||
Crypted: encryptedPwd,
|
||||
PlainAuth: &query.PlainAuth{
|
||||
Password: &crypto.CryptoValue{
|
||||
CryptoType: 0,
|
||||
Algorithm: cryptAlg,
|
||||
KeyID: keyId,
|
||||
Crypted: encryptedPwd,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -60,9 +62,11 @@ func TestNotificationQueries_GetActiveEmailConfig(t *testing.T) {
|
||||
},
|
||||
SMTPConfig: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "mail.com",
|
||||
User: "mail-user",
|
||||
Password: pwd,
|
||||
Host: "mail.com",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "mail-user",
|
||||
Password: pwd,
|
||||
},
|
||||
},
|
||||
Tls: true,
|
||||
From: "[email protected]",
|
||||
@@ -92,7 +96,9 @@ func TestNotificationQueries_GetActiveEmailConfig(t *testing.T) {
|
||||
SMTPConfig: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "mail.com",
|
||||
User: "mail-user",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "mail-user",
|
||||
},
|
||||
},
|
||||
Tls: true,
|
||||
From: "[email protected]",
|
||||
|
||||
@@ -443,9 +443,11 @@ func newNotificationWorker(t *testing.T, ctrl *gomock.Controller, queries *mock.
|
||||
},
|
||||
SMTPConfig: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
Host: "host",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
Tls: true,
|
||||
From: "from",
|
||||
|
||||
@@ -1982,9 +1982,11 @@ func newUserNotifierLegacy(t *testing.T, ctrl *gomock.Controller, queries *mock.
|
||||
},
|
||||
SMTPConfig: &smtp.Config{
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
Host: "host",
|
||||
PlainAuth: &smtp.PlainAuthConfig{
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
Tls: true,
|
||||
From: "from",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SMTPConfigProjectionTable = "projections.smtp_configs5"
|
||||
SMTPConfigProjectionTable = "projections.smtp_configs6"
|
||||
SMTPConfigTable = SMTPConfigProjectionTable + "_" + smtpConfigSMTPTableSuffix
|
||||
SMTPConfigHTTPTable = SMTPConfigProjectionTable + "_" + smtpConfigHTTPTableSuffix
|
||||
|
||||
@@ -25,16 +25,20 @@ const (
|
||||
SMTPConfigColumnState = "state"
|
||||
SMTPConfigColumnDescription = "description"
|
||||
|
||||
smtpConfigSMTPTableSuffix = "smtp"
|
||||
SMTPConfigSMTPColumnInstanceID = "instance_id"
|
||||
SMTPConfigSMTPColumnID = "id"
|
||||
SMTPConfigSMTPColumnTLS = "tls"
|
||||
SMTPConfigSMTPColumnSenderAddress = "sender_address"
|
||||
SMTPConfigSMTPColumnSenderName = "sender_name"
|
||||
SMTPConfigSMTPColumnReplyToAddress = "reply_to_address"
|
||||
SMTPConfigSMTPColumnHost = "host"
|
||||
SMTPConfigSMTPColumnUser = "username"
|
||||
SMTPConfigSMTPColumnPassword = "password"
|
||||
smtpConfigSMTPTableSuffix = "smtp"
|
||||
SMTPConfigSMTPColumnInstanceID = "instance_id"
|
||||
SMTPConfigSMTPColumnID = "id"
|
||||
SMTPConfigSMTPColumnTLS = "tls"
|
||||
SMTPConfigSMTPColumnSenderAddress = "sender_address"
|
||||
SMTPConfigSMTPColumnSenderName = "sender_name"
|
||||
SMTPConfigSMTPColumnReplyToAddress = "reply_to_address"
|
||||
SMTPConfigSMTPColumnHost = "host"
|
||||
SMTPConfigSMTPColumnUser = "username"
|
||||
SMTPConfigSMTPColumnPlainAuthPassword = "password"
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId = "xoauth2auth_client_credentials_client_id"
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret = "xoauth2auth_client_credentials_client_secret"
|
||||
SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint = "xoauth2auth_token_endpoint"
|
||||
SMTPConfigSMTPColumnXOAuth2AuthScope = "xoauth2auth_scope"
|
||||
|
||||
smtpConfigHTTPTableSuffix = "http"
|
||||
SMTPConfigHTTPColumnInstanceID = "instance_id"
|
||||
@@ -77,7 +81,11 @@ func (*smtpConfigProjection) Init() *old_handler.Check {
|
||||
handler.NewColumn(SMTPConfigSMTPColumnReplyToAddress, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnHost, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnUser, handler.ColumnTypeText),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnPassword, handler.ColumnTypeJSONB, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnPlainAuthPassword, handler.ColumnTypeJSONB, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId, handler.ColumnTypeText, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret, handler.ColumnTypeJSONB, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint, handler.ColumnTypeText, handler.Nullable()),
|
||||
handler.NewColumn(SMTPConfigSMTPColumnXOAuth2AuthScope, handler.ColumnTypeTextArray, handler.Nullable()),
|
||||
},
|
||||
handler.NewPrimaryKey(SMTPConfigSMTPColumnInstanceID, SMTPConfigSMTPColumnID),
|
||||
smtpConfigSMTPTableSuffix,
|
||||
@@ -155,6 +163,39 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
|
||||
state = domain.SMTPConfigStateActive
|
||||
}
|
||||
|
||||
columns := []handler.Column{
|
||||
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCol(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
|
||||
handler.NewCol(SMTPConfigSMTPColumnTLS, e.TLS),
|
||||
handler.NewCol(SMTPConfigSMTPColumnSenderAddress, e.SenderAddress),
|
||||
handler.NewCol(SMTPConfigSMTPColumnSenderName, e.SenderName),
|
||||
handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, e.ReplyToAddress),
|
||||
handler.NewCol(SMTPConfigSMTPColumnHost, e.Host),
|
||||
handler.NewCol(SMTPConfigSMTPColumnUser, e.User),
|
||||
}
|
||||
|
||||
if e.PlainAuth != nil {
|
||||
columns = append(columns, removeXoauth()...)
|
||||
columns = append(columns, handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, e.PlainAuth.Password))
|
||||
} else if e.Password != nil {
|
||||
columns = append(columns, removeXoauth()...)
|
||||
columns = append(columns, handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, e.Password))
|
||||
}
|
||||
if e.XOAuth2Auth != nil {
|
||||
columns = append(columns, removePlainAuth()...)
|
||||
columns = append(columns,
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint, e.XOAuth2Auth.TokenEndpoint),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthScope, e.XOAuth2Auth.Scopes),
|
||||
)
|
||||
|
||||
if e.XOAuth2Auth.ClientCredentials != nil {
|
||||
columns = append(columns,
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId, e.XOAuth2Auth.ClientCredentials.ClientId),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret, e.XOAuth2Auth.ClientCredentials.ClientSecret),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return handler.NewMultiStatement(
|
||||
e,
|
||||
handler.AddCreateStatement(
|
||||
@@ -171,22 +212,24 @@ func (p *smtpConfigProjection) reduceSMTPConfigAdded(event eventstore.Event) (*h
|
||||
},
|
||||
),
|
||||
handler.AddCreateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(SMTPConfigSMTPColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCol(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
|
||||
handler.NewCol(SMTPConfigSMTPColumnTLS, e.TLS),
|
||||
handler.NewCol(SMTPConfigSMTPColumnSenderAddress, e.SenderAddress),
|
||||
handler.NewCol(SMTPConfigSMTPColumnSenderName, e.SenderName),
|
||||
handler.NewCol(SMTPConfigSMTPColumnReplyToAddress, e.ReplyToAddress),
|
||||
handler.NewCol(SMTPConfigSMTPColumnHost, e.Host),
|
||||
handler.NewCol(SMTPConfigSMTPColumnUser, e.User),
|
||||
handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password),
|
||||
},
|
||||
columns,
|
||||
handler.WithTableSuffix(smtpConfigSMTPTableSuffix),
|
||||
),
|
||||
), nil
|
||||
}
|
||||
|
||||
func removeXoauth() []handler.Column {
|
||||
return []handler.Column{
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint, nil),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthScope, nil),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId, nil),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret, nil),
|
||||
}
|
||||
}
|
||||
func removePlainAuth() []handler.Column {
|
||||
return []handler.Column{handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, nil)}
|
||||
}
|
||||
|
||||
func (p *smtpConfigProjection) reduceSMTPConfigHTTPAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, err := assertEvent[*instance.SMTPConfigHTTPAddedEvent](event)
|
||||
if err != nil {
|
||||
@@ -307,7 +350,27 @@ func (p *smtpConfigProjection) reduceSMTPConfigChanged(event eventstore.Event) (
|
||||
smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnUser, *e.User))
|
||||
}
|
||||
if e.Password != nil {
|
||||
smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnPassword, *e.Password))
|
||||
smtpColumns = append(smtpColumns, handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, *e.Password))
|
||||
}
|
||||
|
||||
if !e.PlainAuth.IsEmpty() {
|
||||
smtpColumns = append(smtpColumns,
|
||||
handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, e.PlainAuth.Password),
|
||||
)
|
||||
}
|
||||
|
||||
if !e.XOAuth2Auth.IsEmpty() {
|
||||
smtpColumns = append(smtpColumns,
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint, e.XOAuth2Auth.TokenEndpoint),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthScope, e.XOAuth2Auth.Scopes),
|
||||
)
|
||||
|
||||
if !e.XOAuth2Auth.ClientCredentials.IsEmpty() {
|
||||
smtpColumns = append(smtpColumns,
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId, e.XOAuth2Auth.ClientCredentials.ClientId),
|
||||
handler.NewCol(SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret, e.XOAuth2Auth.ClientCredentials.ClientSecret),
|
||||
)
|
||||
}
|
||||
}
|
||||
if len(smtpColumns) > 0 {
|
||||
stmts = append(stmts, handler.AddUpdateStatement(
|
||||
@@ -333,7 +396,7 @@ func (p *smtpConfigProjection) reduceSMTPConfigPasswordChanged(event eventstore.
|
||||
e,
|
||||
handler.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(SMTPConfigSMTPColumnPassword, e.Password),
|
||||
handler.NewCol(SMTPConfigSMTPColumnPlainAuthPassword, e.Password),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SMTPConfigSMTPColumnID, getSMTPConfigID(e.ID, e.Aggregate())),
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -59,7 +59,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"sender",
|
||||
@@ -105,7 +105,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -115,7 +115,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_smtp SET (tls, sender_address, sender_name, reply_to_address, host, username) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"sender",
|
||||
@@ -155,7 +155,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -192,7 +192,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -201,7 +201,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_smtp SET sender_address = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_smtp SET sender_address = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"sender",
|
||||
"config-id",
|
||||
@@ -238,7 +238,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -248,7 +248,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_http SET (endpoint, signing_key) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_http SET (endpoint, signing_key) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"endpoint",
|
||||
anyArg{},
|
||||
@@ -284,7 +284,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, description) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -321,7 +321,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -330,7 +330,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_http SET endpoint = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"endpoint",
|
||||
"config-id",
|
||||
@@ -340,7 +340,8 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "reduceSMTPConfigHTTPChanged, signing key",
|
||||
args: args{
|
||||
event: getEvent(
|
||||
@@ -364,7 +365,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -373,7 +374,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_http SET signing_key = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_http SET signing_key = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
"config-id",
|
||||
@@ -416,7 +417,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
@@ -430,7 +431,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, xoauth2auth_token_endpoint, xoauth2auth_scope, xoauth2auth_client_credentials_client_id, xoauth2auth_client_credentials_client_secret, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"ro-id",
|
||||
@@ -440,6 +441,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
"reply-to",
|
||||
"host",
|
||||
"user",
|
||||
nil, nil, nil, nil,
|
||||
anyArg{},
|
||||
},
|
||||
},
|
||||
@@ -481,7 +483,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
@@ -495,7 +497,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6_smtp (instance_id, id, tls, sender_address, sender_name, reply_to_address, host, username, xoauth2auth_token_endpoint, xoauth2auth_scope, xoauth2auth_client_credentials_client_id, xoauth2auth_client_credentials_client_secret, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"config-id",
|
||||
@@ -505,6 +507,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
"reply-to",
|
||||
"host",
|
||||
"user",
|
||||
nil, nil, nil, nil,
|
||||
anyArg{},
|
||||
},
|
||||
},
|
||||
@@ -538,7 +541,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6 (creation_date, change_date, instance_id, resource_owner, aggregate_id, id, sequence, state, description) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
@@ -552,7 +555,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs5_http (instance_id, id, endpoint, signing_key) VALUES ($1, $2, $3, $4)",
|
||||
expectedStmt: "INSERT INTO projections.smtp_configs6_http (instance_id, id, endpoint, signing_key) VALUES ($1, $2, $3, $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"config-id",
|
||||
@@ -585,7 +588,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -596,7 +599,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -629,7 +632,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (NOT (id = $4)) AND (state = $5) AND (instance_id = $6)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -640,7 +643,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -674,7 +677,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -707,7 +710,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence, state) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -747,7 +750,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5_smtp SET password = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6_smtp SET password = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
"config-id",
|
||||
@@ -755,7 +758,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.smtp_configs5 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.smtp_configs6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -788,7 +791,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs6 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"config-id",
|
||||
"instance-id",
|
||||
@@ -818,7 +821,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs6 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"ro-id",
|
||||
"instance-id",
|
||||
@@ -845,7 +848,7 @@ func TestSMTPConfigProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs5 WHERE (instance_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.smtp_configs6 WHERE (instance_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
|
||||
+109
-16
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
@@ -100,8 +101,24 @@ var (
|
||||
name: projection.SMTPConfigSMTPColumnUser,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnPassword = Column{
|
||||
name: projection.SMTPConfigSMTPColumnPassword,
|
||||
SMTPConfigSMTPColumnPlainAuthPassword = Column{
|
||||
name: projection.SMTPConfigSMTPColumnPlainAuthPassword,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId = Column{
|
||||
name: projection.SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret = Column{
|
||||
name: projection.SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint = Column{
|
||||
name: projection.SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
SMTPConfigSMTPColumnXOAuth2AuthScope = Column{
|
||||
name: projection.SMTPConfigSMTPColumnXOAuth2AuthScope,
|
||||
table: smtpConfigsSMTPTable,
|
||||
}
|
||||
|
||||
@@ -156,7 +173,35 @@ type SMTP struct {
|
||||
ReplyToAddress string
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
PlainAuth *PlainAuth
|
||||
XOAuth2Auth *XOAuth2Auth
|
||||
}
|
||||
|
||||
type PlainAuth struct {
|
||||
Password *crypto.CryptoValue
|
||||
}
|
||||
|
||||
func (a PlainAuth) isEmpty() bool {
|
||||
return a.Password == nil
|
||||
}
|
||||
|
||||
type XOAuth2Auth struct {
|
||||
TokenEndpoint string
|
||||
Scopes []string
|
||||
ClientCredentials *XOAuthClientCredentials
|
||||
}
|
||||
|
||||
func (a XOAuth2Auth) isEmpty() bool {
|
||||
return a.ClientCredentials == nil && a.TokenEndpoint == "" && len(a.Scopes) == 0
|
||||
}
|
||||
|
||||
type XOAuthClientCredentials struct {
|
||||
ClientId string
|
||||
ClientSecret *crypto.CryptoValue
|
||||
}
|
||||
|
||||
func (a XOAuthClientCredentials) isEmpty() bool {
|
||||
return a.ClientId == "" && a.ClientSecret == nil
|
||||
}
|
||||
|
||||
func (q *Queries) SMTPConfigActive(ctx context.Context, resourceOwner string) (config *SMTPConfig, err error) {
|
||||
@@ -229,7 +274,11 @@ func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, er
|
||||
SMTPConfigSMTPColumnReplyToAddress.identifier(),
|
||||
SMTPConfigSMTPColumnHost.identifier(),
|
||||
SMTPConfigSMTPColumnUser.identifier(),
|
||||
SMTPConfigSMTPColumnPassword.identifier(),
|
||||
SMTPConfigSMTPColumnPlainAuthPassword.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthScope.identifier(),
|
||||
|
||||
SMTPConfigHTTPColumnID.identifier(),
|
||||
SMTPConfigHTTPColumnEndpoint.identifier(),
|
||||
@@ -260,7 +309,11 @@ func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, er
|
||||
&smtpConfig.replyToAddress,
|
||||
&smtpConfig.host,
|
||||
&smtpConfig.user,
|
||||
&smtpConfig.password,
|
||||
&smtpConfig.plainAuthPassword,
|
||||
&smtpConfig.xoauth2AuthClientCredentialsClientId,
|
||||
&smtpConfig.xoauth2AuthClientClientCredentialsSecret,
|
||||
&smtpConfig.xoauth2AuthTokenEndpoint,
|
||||
&smtpConfig.xoauth2AuthScope,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
&httpConfig.signingKey,
|
||||
@@ -296,7 +349,11 @@ func prepareSMTPConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMTPConfigs,
|
||||
SMTPConfigSMTPColumnReplyToAddress.identifier(),
|
||||
SMTPConfigSMTPColumnHost.identifier(),
|
||||
SMTPConfigSMTPColumnUser.identifier(),
|
||||
SMTPConfigSMTPColumnPassword.identifier(),
|
||||
SMTPConfigSMTPColumnPlainAuthPassword.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientId.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthClientCredentialsClientSecret.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthTokenEndpoint.identifier(),
|
||||
SMTPConfigSMTPColumnXOAuth2AuthScope.identifier(),
|
||||
|
||||
SMTPConfigHTTPColumnID.identifier(),
|
||||
SMTPConfigHTTPColumnEndpoint.identifier(),
|
||||
@@ -330,7 +387,11 @@ func prepareSMTPConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMTPConfigs,
|
||||
&smtpConfig.replyToAddress,
|
||||
&smtpConfig.host,
|
||||
&smtpConfig.user,
|
||||
&smtpConfig.password,
|
||||
&smtpConfig.plainAuthPassword,
|
||||
&smtpConfig.xoauth2AuthClientCredentialsClientId,
|
||||
&smtpConfig.xoauth2AuthClientClientCredentialsSecret,
|
||||
&smtpConfig.xoauth2AuthTokenEndpoint,
|
||||
&smtpConfig.xoauth2AuthScope,
|
||||
&httpConfig.id,
|
||||
&httpConfig.endpoint,
|
||||
&httpConfig.signingKey,
|
||||
@@ -379,20 +440,51 @@ func (q *Queries) SearchSMTPConfigs(ctx context.Context, queries *SMTPConfigsSea
|
||||
}
|
||||
|
||||
type sqlSmtpConfig struct {
|
||||
id sql.NullString
|
||||
tls sql.NullBool
|
||||
senderAddress sql.NullString
|
||||
senderName sql.NullString
|
||||
replyToAddress sql.NullString
|
||||
host sql.NullString
|
||||
user sql.NullString
|
||||
password *crypto.CryptoValue
|
||||
id sql.NullString
|
||||
tls sql.NullBool
|
||||
senderAddress sql.NullString
|
||||
senderName sql.NullString
|
||||
replyToAddress sql.NullString
|
||||
host sql.NullString
|
||||
user sql.NullString
|
||||
plainAuthPassword *crypto.CryptoValue
|
||||
xoauth2AuthClientCredentialsClientId sql.NullString
|
||||
xoauth2AuthClientClientCredentialsSecret *crypto.CryptoValue
|
||||
xoauth2AuthTokenEndpoint sql.NullString
|
||||
xoauth2AuthScope sql.NullString
|
||||
}
|
||||
|
||||
func (c sqlSmtpConfig) set(smtpConfig *SMTPConfig) {
|
||||
if !c.id.Valid {
|
||||
return
|
||||
}
|
||||
|
||||
plainAuth := &PlainAuth{
|
||||
Password: c.plainAuthPassword,
|
||||
}
|
||||
if plainAuth.isEmpty() {
|
||||
plainAuth = nil
|
||||
}
|
||||
|
||||
scopes := strings.Split(c.xoauth2AuthScope.String, " ")
|
||||
if len(scopes) == 1 && scopes[0] == "" {
|
||||
scopes = nil
|
||||
}
|
||||
xoauth2Auth := &XOAuth2Auth{
|
||||
TokenEndpoint: c.xoauth2AuthTokenEndpoint.String,
|
||||
Scopes: scopes,
|
||||
ClientCredentials: &XOAuthClientCredentials{
|
||||
ClientId: c.xoauth2AuthClientCredentialsClientId.String,
|
||||
ClientSecret: c.xoauth2AuthClientClientCredentialsSecret,
|
||||
},
|
||||
}
|
||||
if xoauth2Auth.ClientCredentials.isEmpty() {
|
||||
xoauth2Auth.ClientCredentials = nil
|
||||
}
|
||||
if xoauth2Auth.isEmpty() {
|
||||
xoauth2Auth = nil
|
||||
}
|
||||
|
||||
smtpConfig.SMTPConfig = &SMTP{
|
||||
TLS: c.tls.Bool,
|
||||
SenderAddress: c.senderAddress.String,
|
||||
@@ -400,7 +492,8 @@ func (c sqlSmtpConfig) set(smtpConfig *SMTPConfig) {
|
||||
ReplyToAddress: c.replyToAddress.String,
|
||||
Host: c.host.String,
|
||||
User: c.user.String,
|
||||
Password: c.password,
|
||||
PlainAuth: plainAuth,
|
||||
XOAuth2Auth: xoauth2Auth,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+104
-48
@@ -14,49 +14,57 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs5.creation_date,` +
|
||||
` projections.smtp_configs5.change_date,` +
|
||||
` projections.smtp_configs5.resource_owner,` +
|
||||
` projections.smtp_configs5.sequence,` +
|
||||
` projections.smtp_configs5.id,` +
|
||||
` projections.smtp_configs5.state,` +
|
||||
` projections.smtp_configs5.description,` +
|
||||
` projections.smtp_configs5_smtp.id,` +
|
||||
` projections.smtp_configs5_smtp.tls,` +
|
||||
` projections.smtp_configs5_smtp.sender_address,` +
|
||||
` projections.smtp_configs5_smtp.sender_name,` +
|
||||
` projections.smtp_configs5_smtp.reply_to_address,` +
|
||||
` projections.smtp_configs5_smtp.host,` +
|
||||
` projections.smtp_configs5_smtp.username,` +
|
||||
` projections.smtp_configs5_smtp.password,` +
|
||||
` projections.smtp_configs5_http.id,` +
|
||||
` projections.smtp_configs5_http.endpoint,` +
|
||||
` projections.smtp_configs5_http.signing_key` +
|
||||
` FROM projections.smtp_configs5` +
|
||||
` LEFT JOIN projections.smtp_configs5_smtp ON projections.smtp_configs5.id = projections.smtp_configs5_smtp.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_smtp.instance_id` +
|
||||
` LEFT JOIN projections.smtp_configs5_http ON projections.smtp_configs5.id = projections.smtp_configs5_http.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_http.instance_id`
|
||||
prepareSMTPConfigsStmt = `SELECT projections.smtp_configs5.creation_date,` +
|
||||
` projections.smtp_configs5.change_date,` +
|
||||
` projections.smtp_configs5.resource_owner,` +
|
||||
` projections.smtp_configs5.sequence,` +
|
||||
` projections.smtp_configs5.id,` +
|
||||
` projections.smtp_configs5.state,` +
|
||||
` projections.smtp_configs5.description,` +
|
||||
` projections.smtp_configs5_smtp.id,` +
|
||||
` projections.smtp_configs5_smtp.tls,` +
|
||||
` projections.smtp_configs5_smtp.sender_address,` +
|
||||
` projections.smtp_configs5_smtp.sender_name,` +
|
||||
` projections.smtp_configs5_smtp.reply_to_address,` +
|
||||
` projections.smtp_configs5_smtp.host,` +
|
||||
` projections.smtp_configs5_smtp.username,` +
|
||||
` projections.smtp_configs5_smtp.password,` +
|
||||
` projections.smtp_configs5_http.id,` +
|
||||
` projections.smtp_configs5_http.endpoint,` +
|
||||
` projections.smtp_configs5_http.signing_key,` +
|
||||
prepareSMTPConfigStmt = `SELECT projections.smtp_configs6.creation_date,` +
|
||||
` projections.smtp_configs6.change_date,` +
|
||||
` projections.smtp_configs6.resource_owner,` +
|
||||
` projections.smtp_configs6.sequence,` +
|
||||
` projections.smtp_configs6.id,` +
|
||||
` projections.smtp_configs6.state,` +
|
||||
` projections.smtp_configs6.description,` +
|
||||
` projections.smtp_configs6_smtp.id,` +
|
||||
` projections.smtp_configs6_smtp.tls,` +
|
||||
` projections.smtp_configs6_smtp.sender_address,` +
|
||||
` projections.smtp_configs6_smtp.sender_name,` +
|
||||
` projections.smtp_configs6_smtp.reply_to_address,` +
|
||||
` projections.smtp_configs6_smtp.host,` +
|
||||
` projections.smtp_configs6_smtp.username,` +
|
||||
` projections.smtp_configs6_smtp.password,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_client_credentials_client_id,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_client_credentials_client_secret,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_token_endpoint,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_scope,` +
|
||||
` projections.smtp_configs6_http.id,` +
|
||||
` projections.smtp_configs6_http.endpoint,` +
|
||||
` projections.smtp_configs6_http.signing_key` +
|
||||
` FROM projections.smtp_configs6` +
|
||||
` LEFT JOIN projections.smtp_configs6_smtp ON projections.smtp_configs6.id = projections.smtp_configs6_smtp.id AND projections.smtp_configs6.instance_id = projections.smtp_configs6_smtp.instance_id` +
|
||||
` LEFT JOIN projections.smtp_configs6_http ON projections.smtp_configs6.id = projections.smtp_configs6_http.id AND projections.smtp_configs6.instance_id = projections.smtp_configs6_http.instance_id`
|
||||
prepareSMTPConfigsStmt = `SELECT projections.smtp_configs6.creation_date,` +
|
||||
` projections.smtp_configs6.change_date,` +
|
||||
` projections.smtp_configs6.resource_owner,` +
|
||||
` projections.smtp_configs6.sequence,` +
|
||||
` projections.smtp_configs6.id,` +
|
||||
` projections.smtp_configs6.state,` +
|
||||
` projections.smtp_configs6.description,` +
|
||||
` projections.smtp_configs6_smtp.id,` +
|
||||
` projections.smtp_configs6_smtp.tls,` +
|
||||
` projections.smtp_configs6_smtp.sender_address,` +
|
||||
` projections.smtp_configs6_smtp.sender_name,` +
|
||||
` projections.smtp_configs6_smtp.reply_to_address,` +
|
||||
` projections.smtp_configs6_smtp.host,` +
|
||||
` projections.smtp_configs6_smtp.username,` +
|
||||
` projections.smtp_configs6_smtp.password,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_client_credentials_client_id,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_client_credentials_client_secret,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_token_endpoint,` +
|
||||
` projections.smtp_configs6_smtp.xoauth2auth_scope,` +
|
||||
` projections.smtp_configs6_http.id,` +
|
||||
` projections.smtp_configs6_http.endpoint,` +
|
||||
` projections.smtp_configs6_http.signing_key,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.smtp_configs5` +
|
||||
` LEFT JOIN projections.smtp_configs5_smtp ON projections.smtp_configs5.id = projections.smtp_configs5_smtp.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_smtp.instance_id` +
|
||||
` LEFT JOIN projections.smtp_configs5_http ON projections.smtp_configs5.id = projections.smtp_configs5_http.id AND projections.smtp_configs5.instance_id = projections.smtp_configs5_http.instance_id`
|
||||
` FROM projections.smtp_configs6` +
|
||||
` LEFT JOIN projections.smtp_configs6_smtp ON projections.smtp_configs6.id = projections.smtp_configs6_smtp.id AND projections.smtp_configs6.instance_id = projections.smtp_configs6_smtp.instance_id` +
|
||||
` LEFT JOIN projections.smtp_configs6_http ON projections.smtp_configs6.id = projections.smtp_configs6_http.id AND projections.smtp_configs6.instance_id = projections.smtp_configs6_http.instance_id`
|
||||
|
||||
prepareSMTPConfigCols = []string{
|
||||
"creation_date",
|
||||
@@ -74,6 +82,10 @@ var (
|
||||
"smtp_host",
|
||||
"smtp_user",
|
||||
"smtp_password",
|
||||
"xoauth2auth_client_credentials_client_id",
|
||||
"xoauth2auth_client_credentials_client_secret",
|
||||
"xoauth2auth_token_endpoint",
|
||||
"xoauth2auth_scope",
|
||||
"id",
|
||||
"endpoint",
|
||||
"signing_key",
|
||||
@@ -136,6 +148,10 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -151,7 +167,9 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
@@ -181,6 +199,10 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"2232323",
|
||||
"endpoint",
|
||||
&crypto.CryptoValue{
|
||||
@@ -237,6 +259,10 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -252,7 +278,9 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to2",
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "44442323",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
@@ -285,6 +313,10 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -300,7 +332,9 @@ func Test_SMTPConfigPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to3",
|
||||
Host: "host3",
|
||||
User: "user3",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "23234444",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
@@ -383,6 +417,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -404,7 +442,9 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to",
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "2232323",
|
||||
State: domain.SMTPConfigStateActive,
|
||||
@@ -437,6 +477,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
"2232323",
|
||||
"endpoint",
|
||||
&crypto.CryptoValue{
|
||||
@@ -465,6 +509,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
testNow,
|
||||
@@ -485,6 +533,10 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
},
|
||||
),
|
||||
@@ -524,7 +576,9 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to2",
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "44442323",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
@@ -542,7 +596,9 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
|
||||
ReplyToAddress: "reply-to3",
|
||||
Host: "host3",
|
||||
User: "user3",
|
||||
Password: &crypto.CryptoValue{},
|
||||
PlainAuth: &PlainAuth{
|
||||
Password: &crypto.CryptoValue{},
|
||||
},
|
||||
},
|
||||
ID: "23234444",
|
||||
State: domain.SMTPConfigStateInactive,
|
||||
|
||||
@@ -33,6 +33,23 @@ type SMTPConfigAddedEvent struct {
|
||||
Host string `json:"host,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
PlainAuth *PlainAuth `json:"plainAuth,omitempty"`
|
||||
XOAuth2Auth *XOAuth2Auth `json:"xoauth2Auth,omitempty"`
|
||||
}
|
||||
|
||||
type XOAuth2Auth struct {
|
||||
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
ClientCredentials *XOAuth2ClientCredentials `json:"clientCredentials,omitempty"`
|
||||
}
|
||||
|
||||
type XOAuth2ClientCredentials struct {
|
||||
ClientId string `json:"clientId,omitempty"`
|
||||
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
|
||||
}
|
||||
|
||||
type PlainAuth struct {
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func NewSMTPConfigAddedEvent(
|
||||
@@ -43,9 +60,10 @@ func NewSMTPConfigAddedEvent(
|
||||
senderAddress,
|
||||
senderName,
|
||||
replyToAddress,
|
||||
host,
|
||||
host string,
|
||||
user string,
|
||||
password *crypto.CryptoValue,
|
||||
plainAuth *PlainAuth,
|
||||
xoauth2Auth *XOAuth2Auth,
|
||||
) *SMTPConfigAddedEvent {
|
||||
return &SMTPConfigAddedEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
@@ -61,9 +79,11 @@ func NewSMTPConfigAddedEvent(
|
||||
ReplyToAddress: replyToAddress,
|
||||
Host: host,
|
||||
User: user,
|
||||
Password: password,
|
||||
PlainAuth: plainAuth,
|
||||
XOAuth2Auth: xoauth2Auth,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *SMTPConfigAddedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
e.BaseEvent = event
|
||||
}
|
||||
@@ -87,6 +107,35 @@ type SMTPConfigChangedEvent struct {
|
||||
Host *string `json:"host,omitempty"`
|
||||
User *string `json:"user,omitempty"`
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
PlainAuth PlainAuthChanged `json:"plainAuth,omitempty"`
|
||||
XOAuth2Auth XOAuth2AuthChanged `json:"xoauth2Auth,omitempty"`
|
||||
}
|
||||
|
||||
type XOAuth2AuthChanged struct {
|
||||
TokenEndpoint *string `json:"tokenEndpoint,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
ClientCredentials XOAuth2ClientCredentialsChanged `json:"clientCredentials,omitempty"`
|
||||
}
|
||||
|
||||
func (c XOAuth2AuthChanged) IsEmpty() bool {
|
||||
return c.ClientCredentials.IsEmpty() && c.TokenEndpoint == nil && len(c.Scopes) == 0
|
||||
}
|
||||
|
||||
type XOAuth2ClientCredentialsChanged struct {
|
||||
ClientId *string `json:"clientId,omitempty"`
|
||||
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
|
||||
}
|
||||
|
||||
func (c XOAuth2ClientCredentialsChanged) IsEmpty() bool {
|
||||
return c.ClientId == nil && c.ClientSecret == nil
|
||||
}
|
||||
|
||||
type PlainAuthChanged struct {
|
||||
Password *crypto.CryptoValue `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (c PlainAuthChanged) IsEmpty() bool {
|
||||
return c.Password == nil
|
||||
}
|
||||
|
||||
func (e *SMTPConfigChangedEvent) SetBaseEvent(event *eventstore.BaseEvent) {
|
||||
@@ -177,6 +226,31 @@ func ChangeSMTPConfigSMTPUser(smtpUser string) func(event *SMTPConfigChangedEven
|
||||
func ChangeSMTPConfigSMTPPassword(password *crypto.CryptoValue) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.Password = password
|
||||
e.PlainAuth.Password = password
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigXOAuth2ClientCredentialsClientId(clientId string) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.XOAuth2Auth.ClientCredentials.ClientId = &clientId
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigXOAuth2ClientCredentialsClientSecret(clientSecret *crypto.CryptoValue) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.XOAuth2Auth.ClientCredentials.ClientSecret = clientSecret
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigXOAuth2TokenEndpoint(tokenEndpoint string) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.XOAuth2Auth.TokenEndpoint = &tokenEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSMTPConfigXOAuth2Scopes(scopes []string) func(event *SMTPConfigChangedEvent) {
|
||||
return func(e *SMTPConfigChangedEvent) {
|
||||
e.XOAuth2Auth.Scopes = scopes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4944,6 +4944,7 @@ message AddEmailProviderSMTPRequest {
|
||||
example: "\"197f0117-529e-443d-bf6c-0292dd9a02b7\"";
|
||||
}
|
||||
];
|
||||
// Deprecated: use [Auth] oneof instead.
|
||||
string password = 6 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"this-is-my-password\"";
|
||||
@@ -4965,6 +4966,78 @@ message AddEmailProviderSMTPRequest {
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
oneof Auth {
|
||||
SMTPNoAuth none = 9;
|
||||
SMTPPlainAuth plain = 10;
|
||||
SMTPXOAuth2Auth xoauth2 = 11;
|
||||
}
|
||||
}
|
||||
|
||||
// SMTPNoAuth can be used when no authentication is required for the SMTP connection.
|
||||
message SMTPNoAuth {}
|
||||
|
||||
// SMTPPlainAuth adds plain authentication to the smtp connection. The username of the parent configuration is used in
|
||||
// combination with the password in this message.
|
||||
message SMTPPlainAuth {
|
||||
string password = 1 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"this-is-my-client-secret\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// SMTPXOAuth2Auth adds XOAut2 authentication to the smtp connection. The username of the parent configuration is used
|
||||
// in combination with the other parameters of this message.
|
||||
message SMTPXOAuth2Auth {
|
||||
// token_endpoint is the endpoint from which a token will be requested according to the oauth2 specification.
|
||||
string token_endpoint = 1 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"http://auth.example.com/token\"";
|
||||
min_length: 0;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
// scopes is a list of scopes which should be requested from the authorization service. To authorize a token to
|
||||
// use the smtp functionality, the server requires a specific scope. These scopes can be found in the documentation
|
||||
// of the provider.
|
||||
repeated string scopes = 2 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}},
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "[\"https://mail.example.com\"]";
|
||||
}
|
||||
];
|
||||
// OAuth2Type is a oneof used to switch between the different types of oauth2 authorization flows.
|
||||
oneof OAuth2Type {
|
||||
ClientCredentials client_credentials = 3;
|
||||
}
|
||||
|
||||
// ClientCredentials authenticates the SMTP client using Oauth 2.0 Client Credentials grant.
|
||||
// https://datatracker.ietf.org/doc/html/rfc6749#section-4.4
|
||||
message ClientCredentials {
|
||||
string client_id = 1 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"197f0117-529e-443d-bf6c-0292dd9a02b7\"";
|
||||
min_length: 0;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
string client_secret = 2 [
|
||||
(validate.rules).string = {min_len: 0, max_len: 200},
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"this-is-my-client-secret\"";
|
||||
min_length: 0;
|
||||
max_length: 200;
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
message AddEmailProviderSMTPResponse {
|
||||
@@ -5029,6 +5102,11 @@ message UpdateEmailProviderSMTPRequest {
|
||||
}
|
||||
];
|
||||
string id = 9 [(validate.rules).string = {min_len: 1, max_len: 100}];
|
||||
oneof Auth {
|
||||
SMTPNoAuth none = 10;
|
||||
SMTPPlainAuth plain = 11;
|
||||
SMTPXOAuth2Auth xoauth2 = 12;
|
||||
}
|
||||
}
|
||||
|
||||
message UpdateEmailProviderSMTPResponse {
|
||||
@@ -5221,6 +5299,12 @@ message TestEmailProviderSMTPRequest {
|
||||
example: "\"267191369515139464\"";
|
||||
}
|
||||
];
|
||||
oneof Auth {
|
||||
option (validate.required) = true;
|
||||
SMTPNoAuth none = 9;
|
||||
SMTPPlainAuth plain = 10;
|
||||
SMTPXOAuth2Auth xoauth2 = 11;
|
||||
}
|
||||
}
|
||||
|
||||
// This is an empty response
|
||||
|
||||
@@ -140,6 +140,51 @@ message EmailProviderSMTP {
|
||||
example: "\"replyto@m.zitadel.cloud\"";
|
||||
}
|
||||
];
|
||||
oneof Auth {
|
||||
SMTPNoAuth none = 9;
|
||||
SMTPPlainAuth plain = 10;
|
||||
SMTPXOAuth2Auth xoauth2 = 11;
|
||||
}
|
||||
}
|
||||
|
||||
// SMTPNoAuth can be used when no authentication is required for the SMTP connection.
|
||||
message SMTPNoAuth {}
|
||||
|
||||
// SMTPPlainAuth adds plain authentication to the smtp connection. The username of the parent configuration is used in
|
||||
// combination with the password in this message.
|
||||
message SMTPPlainAuth {}
|
||||
|
||||
// SMTPXOAuth2Auth adds XOAut2 authentication to the smtp connection. The username of the parent configuration is used
|
||||
// in combination with the other parameters of this message.
|
||||
message SMTPXOAuth2Auth {
|
||||
// token_endpoint is the endpoint from which a token will be requested according to the oauth2 specification.
|
||||
string token_endpoint = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"http://auth.example.com/token\"";
|
||||
}
|
||||
];
|
||||
// scopes is a list of scopes which should be requested from the authorization service. To authorize a token to
|
||||
// use the smtp functionality, the server requires a specific scope. These scopes can be found in the documentation
|
||||
// of the provider.
|
||||
repeated string scopes = 2 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "[\"https://mail.example.com\"]";
|
||||
}
|
||||
];
|
||||
// OAuth2Type is a oneof used to switch between the different types of oauth2 authorization flows.
|
||||
oneof OAuth2Type {
|
||||
ClientCredentials client_credentials = 3;
|
||||
}
|
||||
|
||||
// ClientCredentials authenticates the SMTP client using Oauth 2.0 Client Credentials grant.
|
||||
// https://datatracker.ietf.org/doc/html/rfc6749#section-4.4
|
||||
message ClientCredentials {
|
||||
string client_id = 1 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
example: "\"197f0117-529e-443d-bf6c-0292dd9a02b7\"";
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
message EmailProviderHTTP {
|
||||
|
||||
Reference in New Issue
Block a user