mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
# Which Problems Are Solved As part of https://github.com/zitadel/zitadel/issues/9599 to push to move to a relational db table model, this is the migration of the settings # Additional Changes I had to add 2 non source code files `backend/v3/storage/database/events_testing/font.otf` and `backend/v3/storage/database/events_testing/picture.png`, these are used as part of the reduce tests, hence why they're sourced inside `backend/v3/storage/database/events_testing/settings_instance_test.go` - Closes https://github.com/zitadel/zitadel/issues/10207 --------- Co-authored-by: adlerhurst <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Tim Möhlmann <[email protected]> Co-authored-by: Stefan Benz <[email protected]>
4757 lines
150 KiB
Go
4757 lines
150 KiB
Go
package repository_test
|
|
|
|
import (
|
|
"net/url"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/muhlemmer/gu"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/zitadel/zitadel/backend/v3/domain"
|
|
"github.com/zitadel/zitadel/backend/v3/storage/database"
|
|
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
|
|
)
|
|
|
|
func TestGetLoginSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LoginSettingsRepository()
|
|
|
|
settings := []*domain.LoginSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri2"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri2"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.LoginSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListLoginSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LoginSettingsRepository()
|
|
|
|
settings := []*domain.LoginSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri2"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri2"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.LoginSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.LoginSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.LoginSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.LoginSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.LoginSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetLoginSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LoginSettingsRepository()
|
|
|
|
existingSettings := &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri2"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.LoginSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(true),
|
|
AllowRegister: gu.Ptr(true),
|
|
AllowExternalIDP: gu.Ptr(true),
|
|
ForceMFA: gu.Ptr(true),
|
|
ForceMFALocalOnly: gu.Ptr(true),
|
|
HidePasswordReset: gu.Ptr(true),
|
|
IgnoreUnknownUsernames: gu.Ptr(true),
|
|
AllowDomainDiscovery: gu.Ptr(true),
|
|
DisableLoginWithEmail: gu.Ptr(true),
|
|
DisableLoginWithPhone: gu.Ptr(true),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Hour),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Hour),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Hour),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Hour),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteLoginSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LoginSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.LoginSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LoginSettingsAttributes: domain.LoginSettingsAttributes{
|
|
AllowUserNamePassword: gu.Ptr(false),
|
|
AllowRegister: gu.Ptr(false),
|
|
AllowExternalIDP: gu.Ptr(false),
|
|
ForceMFA: gu.Ptr(false),
|
|
ForceMFALocalOnly: gu.Ptr(false),
|
|
HidePasswordReset: gu.Ptr(false),
|
|
IgnoreUnknownUsernames: gu.Ptr(false),
|
|
AllowDomainDiscovery: gu.Ptr(false),
|
|
DisableLoginWithEmail: gu.Ptr(false),
|
|
DisableLoginWithPhone: gu.Ptr(false),
|
|
PasswordlessType: gu.Ptr(domain.PasswordlessTypeNotAllowed),
|
|
DefaultRedirectURI: gu.Ptr("uri"),
|
|
PasswordCheckLifetime: gu.Ptr(time.Minute),
|
|
ExternalLoginCheckLifetime: gu.Ptr(time.Minute),
|
|
MFAInitSkipLifetime: gu.Ptr(time.Minute),
|
|
SecondFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
MultiFactorCheckLifetime: gu.Ptr(time.Minute),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(instanceID, gu.Ptr("foo"), domain.SettingTypeLogin, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLogin, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLogin, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLogin, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLogin, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
settings := []*domain.BrandingSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
_, err := repo.Activate(t.Context(), tx, repo.UniqueCondition(settings[0].InstanceID, settings[0].OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview))
|
|
require.NoError(t, err)
|
|
activeInstanceSetting := *settings[0]
|
|
activeInstanceSetting.State = domain.SettingStateActive
|
|
|
|
_, err = repo.Activate(t.Context(), tx, repo.UniqueCondition(settings[3].InstanceID, settings[3].OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview))
|
|
require.NoError(t, err)
|
|
activeOrganizationSetting := *settings[3]
|
|
activeOrganizationSetting.State = domain.SettingStateActive
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.BrandingSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: database.And(
|
|
repo.PrimaryKeyCondition(settings[0].InstanceID, settings[0].ID),
|
|
repo.StateCondition(domain.SettingStatePreview),
|
|
),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, instance, active",
|
|
condition: database.And(
|
|
repo.PrimaryKeyCondition(activeInstanceSetting.InstanceID, activeInstanceSetting.ID),
|
|
repo.StateCondition(domain.SettingStateActive),
|
|
),
|
|
want: &activeInstanceSetting,
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: database.And(
|
|
repo.PrimaryKeyCondition(settings[3].InstanceID, settings[3].ID),
|
|
repo.StateCondition(domain.SettingStatePreview),
|
|
),
|
|
want: settings[3],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: database.And(
|
|
repo.PrimaryKeyCondition(activeOrganizationSetting.InstanceID, activeOrganizationSetting.ID),
|
|
repo.StateCondition(domain.SettingStateActive),
|
|
),
|
|
want: &activeOrganizationSetting,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
settings := []*domain.BrandingSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
_, err := repo.Activate(t.Context(), tx, repo.UniqueCondition(settings[0].InstanceID, settings[0].OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview))
|
|
require.NoError(t, err)
|
|
activeInstanceSetting := *settings[0]
|
|
activeInstanceSetting.State = domain.SettingStateActive
|
|
|
|
_, err = repo.Activate(t.Context(), tx, repo.UniqueCondition(settings[2].InstanceID, settings[2].OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview))
|
|
require.NoError(t, err)
|
|
activeOrganizationSetting := *settings[2]
|
|
activeOrganizationSetting.State = domain.SettingStateActive
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.BrandingSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.BrandingSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.BrandingSettings{&activeOrganizationSetting, settings[2], &activeInstanceSetting, settings[0]},
|
|
},
|
|
{
|
|
name: "all from instance, preview",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.StateCondition(domain.SettingStatePreview),
|
|
),
|
|
want: []*domain.BrandingSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "all from instance, active",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.StateCondition(domain.SettingStateActive),
|
|
),
|
|
want: []*domain.BrandingSettings{&activeOrganizationSetting, &activeInstanceSetting},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.BrandingSettings{&activeInstanceSetting, settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.BrandingSettings{&activeOrganizationSetting, settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn(), repo.StateColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
|
|
if !assert.Len(t, got, len(tt.want)) {
|
|
return
|
|
}
|
|
for i := range got {
|
|
assert.EqualExportedValues(t, tt.want[i], got[i])
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
existingSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.BrandingSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestActivateBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
wantRowsAffected int64
|
|
condition database.Condition
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "activate instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingInstanceSettings.InstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "activate organization",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingOrganizationSettings.InstanceID),
|
|
repo.OrganizationIDCondition(existingOrganizationSettings.OrganizationID),
|
|
),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition("foo"),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
wantRowsAffected: 0,
|
|
},
|
|
|
|
{
|
|
name: "non-existing organization",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingOrganizationSettings.InstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr("foo")),
|
|
),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
rowsAffected, err := repo.Activate(t.Context(), savepoint, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestActivateAtBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
wantRowsAffected int64
|
|
condition database.Condition
|
|
updatedAt time.Time
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "activate instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingInstanceSettings.InstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "activate organization",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingOrganizationSettings.InstanceID),
|
|
repo.OrganizationIDCondition(existingOrganizationSettings.OrganizationID),
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition("foo"),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 0,
|
|
},
|
|
|
|
{
|
|
name: "non-existing organization",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(existingOrganizationSettings.InstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr("foo")),
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
rowsAffected, err := repo.ActivateAt(t.Context(), savepoint, tt.condition, tt.updatedAt)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteBrandingSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.BrandingSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
_, err = repo.Activate(t.Context(), tx,
|
|
database.And(
|
|
repo.InstanceIDCondition(existingInstanceSettings.InstanceID),
|
|
repo.OrganizationIDCondition(existingInstanceSettings.OrganizationID),
|
|
),
|
|
)
|
|
require.NoError(t, err)
|
|
activeInstanceSetting := *existingInstanceSettings
|
|
activeInstanceSetting.State = domain.SettingStateActive
|
|
|
|
existingOrganizationSettings := &domain.BrandingSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
BrandingSettingsAttributes: domain.BrandingSettingsAttributes{
|
|
PrimaryColorLight: gu.Ptr("color"),
|
|
BackgroundColorLight: gu.Ptr("color"),
|
|
WarnColorLight: gu.Ptr("color"),
|
|
FontColorLight: gu.Ptr("color"),
|
|
LogoURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLLight: &url.URL{Scheme: "https", Host: "host"},
|
|
PrimaryColorDark: gu.Ptr("color"),
|
|
BackgroundColorDark: gu.Ptr("color"),
|
|
WarnColorDark: gu.Ptr("color"),
|
|
FontColorDark: gu.Ptr("color"),
|
|
LogoURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
IconURLDark: &url.URL{Scheme: "https", Host: "host"},
|
|
HideLoginNameSuffix: gu.Ptr(true),
|
|
ErrorMsgPopup: gu.Ptr(true),
|
|
DisableWatermark: gu.Ptr(true),
|
|
ThemeMode: gu.Ptr(domain.BrandingPolicyThemeAuto),
|
|
FontURL: &url.URL{Scheme: "https", Host: "host"},
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
_, err = repo.Activate(t.Context(), tx,
|
|
database.And(
|
|
repo.InstanceIDCondition(existingOrganizationSettings.InstanceID),
|
|
repo.OrganizationIDCondition(existingOrganizationSettings.OrganizationID),
|
|
),
|
|
)
|
|
require.NoError(t, err)
|
|
activeOrganizationSetting := *existingOrganizationSettings
|
|
activeOrganizationSetting.State = domain.SettingStateActive
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeBranding, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance, active",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization, active",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice, active",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeBranding, domain.SettingStatePreview),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetPasswordComplexitySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.PasswordComplexitySettingsRepository()
|
|
|
|
settings := []*domain.PasswordComplexitySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(10)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(12)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(14)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.PasswordComplexitySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListPasswordComplexitySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.PasswordComplexitySettingsRepository()
|
|
|
|
settings := []*domain.PasswordComplexitySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(10)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(10)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(12)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.PasswordComplexitySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.PasswordComplexitySettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.PasswordComplexitySettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.PasswordComplexitySettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.PasswordComplexitySettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetPasswordComplexitySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.PasswordComplexitySettingsRepository()
|
|
|
|
existingSettings := &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.PasswordComplexitySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(10)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeletePasswordComplexitySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.PasswordComplexitySettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.PasswordComplexitySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordComplexitySettingsAttributes: domain.PasswordComplexitySettingsAttributes{
|
|
MinLength: gu.Ptr(uint64(8)),
|
|
HasLowercase: gu.Ptr(true),
|
|
HasUppercase: gu.Ptr(true),
|
|
HasNumber: gu.Ptr(true),
|
|
HasSymbol: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypePasswordComplexity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypePasswordComplexity, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypePasswordComplexity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypePasswordComplexity, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypePasswordComplexity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetPasswordExpirySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.PasswordExpirySettingsRepository()
|
|
|
|
settings := []*domain.PasswordExpirySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(11)),
|
|
MaxAgeDays: gu.Ptr(uint64(31)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(12)),
|
|
MaxAgeDays: gu.Ptr(uint64(32)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(13)),
|
|
MaxAgeDays: gu.Ptr(uint64(33)),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.PasswordExpirySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListPasswordExpirySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.PasswordExpirySettingsRepository()
|
|
|
|
settings := []*domain.PasswordExpirySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(11)),
|
|
MaxAgeDays: gu.Ptr(uint64(31)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(12)),
|
|
MaxAgeDays: gu.Ptr(uint64(32)),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(13)),
|
|
MaxAgeDays: gu.Ptr(uint64(33)),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.PasswordExpirySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.PasswordExpirySettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.PasswordExpirySettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.PasswordExpirySettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.PasswordExpirySettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetPasswordExpirySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.PasswordExpirySettingsRepository()
|
|
|
|
existingSettings := &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.PasswordExpirySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeletePasswordExpirySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.PasswordExpirySettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.PasswordExpirySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
PasswordExpirySettingsAttributes: domain.PasswordExpirySettingsAttributes{
|
|
ExpireWarnDays: gu.Ptr(uint64(10)),
|
|
MaxAgeDays: gu.Ptr(uint64(30)),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypePasswordExpiry, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypePasswordExpiry, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypePasswordExpiry, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypePasswordExpiry, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypePasswordExpiry, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetLockoutSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LockoutSettingsRepository()
|
|
|
|
settings := []*domain.LockoutSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(4)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(4)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(5)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(5)),
|
|
ShowLockOutFailures: gu.Ptr(false),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(6)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(6)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.LockoutSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListLockoutSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LockoutSettingsRepository()
|
|
|
|
settings := []*domain.LockoutSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(4)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(4)),
|
|
ShowLockOutFailures: gu.Ptr(false),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(5)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(5)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(6)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(6)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.LockoutSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.LockoutSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.LockoutSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.LockoutSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.LockoutSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetLockoutSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LockoutSettingsRepository()
|
|
|
|
existingSettings := &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.LockoutSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(4)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(4)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(5)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(5)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteLockoutSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LockoutSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(3)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(3)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.LockoutSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LockoutSettingsAttributes: domain.LockoutSettingsAttributes{
|
|
MaxPasswordAttempts: gu.Ptr(uint64(4)),
|
|
MaxOTPAttempts: gu.Ptr(uint64(4)),
|
|
ShowLockOutFailures: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeLockout, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLockout, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLockout, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLockout, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLockout, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSecuritySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.SecuritySettingsRepository()
|
|
|
|
settings := []*domain.SecuritySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin3", "origin4"},
|
|
EnableImpersonation: gu.Ptr(false),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin5", "origin6"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(false),
|
|
AllowedOrigins: []string{"origin7", "origin8"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.SecuritySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListSecuritySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.SecuritySettingsRepository()
|
|
|
|
settings := []*domain.SecuritySettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin3", "origin4"},
|
|
EnableImpersonation: gu.Ptr(false),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin5", "origin6"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(false),
|
|
AllowedOrigins: []string{"origin7", "origin8"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.SecuritySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.SecuritySettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.SecuritySettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.SecuritySettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.SecuritySettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetSecuritySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.SecuritySettingsRepository()
|
|
|
|
existingSettings := &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.SecuritySettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteSecuritySettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.SecuritySettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin1", "origin2"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.SecuritySettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
SecuritySettingsAttributes: domain.SecuritySettingsAttributes{
|
|
EnableIframeEmbedding: gu.Ptr(true),
|
|
AllowedOrigins: []string{"origin3", "origin4"},
|
|
EnableImpersonation: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeSecurity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecurity, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecurity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecurity, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecurity, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetDomainSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.DomainSettingsRepository()
|
|
|
|
settings := []*domain.DomainSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(false),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(false),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(false),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.DomainSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListDomainSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.DomainSettingsRepository()
|
|
|
|
settings := []*domain.DomainSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(false),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(false),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(false),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.DomainSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.DomainSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.DomainSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.DomainSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.DomainSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetDomainSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.DomainSettingsRepository()
|
|
|
|
existingSettings := &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.DomainSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteDomainSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.DomainSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(true),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.DomainSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
DomainSettingsAttributes: domain.DomainSettingsAttributes{
|
|
LoginNameIncludesDomain: gu.Ptr(true),
|
|
RequireOrgDomainVerification: gu.Ptr(false),
|
|
SMTPSenderAddressMatchesInstanceDomain: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeDomain, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeDomain, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeDomain, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeDomain, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeDomain, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetOrganizationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.OrganizationSettingsRepository()
|
|
|
|
settings := []*domain.OrganizationSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.OrganizationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListOrganizationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.OrganizationSettingsRepository()
|
|
|
|
settings := []*domain.OrganizationSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.OrganizationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.OrganizationSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.OrganizationSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.OrganizationSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.OrganizationSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetOrganizationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.OrganizationSettingsRepository()
|
|
|
|
existingSettings := &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.OrganizationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteOrganizationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.OrganizationSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.OrganizationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
OrganizationSettingsAttributes: domain.OrganizationSettingsAttributes{
|
|
OrganizationScopedUsernames: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeOrganization, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeOrganization, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeOrganization, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeOrganization, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeOrganization, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetNotificationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.NotificationSettingsRepository()
|
|
|
|
settings := []*domain.NotificationSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.NotificationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListNotificationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.NotificationSettingsRepository()
|
|
|
|
settings := []*domain.NotificationSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.NotificationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.NotificationSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.NotificationSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.NotificationSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.NotificationSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetNotificationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.NotificationSettingsRepository()
|
|
|
|
existingSettings := &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.NotificationSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteNotificationSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.NotificationSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.NotificationSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
NotificationSettingsAttributes: domain.NotificationSettingsAttributes{
|
|
PasswordChange: gu.Ptr(true),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeNotification, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeNotification, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeNotification, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeNotification, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeNotification, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetLegalAndSupportSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LegalAndSupportSettingsRepository()
|
|
|
|
settings := []*domain.LegalAndSupportSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.LegalAndSupportSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.IDCondition(settings[0].ID),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
wantErr: database.NewNoRowFoundError(nil),
|
|
},
|
|
{
|
|
name: "too many",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
wantErr: database.NewMultipleRowsFoundError(nil),
|
|
},
|
|
{
|
|
name: "ok, instance",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
|
|
want: settings[0],
|
|
},
|
|
{
|
|
name: "ok, organization",
|
|
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
|
|
want: settings[3],
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListLegalAndSupportSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
firstInstanceID := createInstance(t, tx)
|
|
secondInstanceID := createInstance(t, tx)
|
|
firstOrgID := createOrganization(t, tx, firstInstanceID)
|
|
secondOrgID := createOrganization(t, tx, secondInstanceID)
|
|
repo := repository.LegalAndSupportSettingsRepository()
|
|
|
|
settings := []*domain.LegalAndSupportSettings{
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: firstInstanceID,
|
|
OrganizationID: gu.Ptr(firstOrgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
{
|
|
Settings: domain.Settings{
|
|
InstanceID: secondInstanceID,
|
|
OrganizationID: gu.Ptr(secondOrgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.LegalAndSupportSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "no results, ok",
|
|
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
|
|
want: []*domain.LegalAndSupportSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.LegalAndSupportSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.LegalAndSupportSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.LegalAndSupportSettings{settings[2]},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := repo.List(t.Context(), tx,
|
|
database.WithCondition(tt.condition),
|
|
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
|
|
)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.EqualExportedValues(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetLegalAndSupportSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LegalAndSupportSettingsRepository()
|
|
|
|
existingSettings := &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
}
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.LegalAndSupportSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: "foo",
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr("foo"),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
},
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
savepoint, rollback := savepointForRollback(t, tx)
|
|
defer rollback()
|
|
err := repo.Set(t.Context(), savepoint, tt.settings)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeleteLegalAndSupportSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.LegalAndSupportSettingsRepository()
|
|
|
|
existingInstanceSettings := &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: nil,
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
}
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := &domain.LegalAndSupportSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: gu.Ptr(orgID),
|
|
},
|
|
LegalAndSupportSettingsAttributes: domain.LegalAndSupportSettingsAttributes{
|
|
TOSLink: gu.Ptr("https://host"),
|
|
PrivacyPolicyLink: gu.Ptr("https://host"),
|
|
HelpLink: gu.Ptr("https://host"),
|
|
SupportEmail: gu.Ptr("email"),
|
|
DocsLink: gu.Ptr("https://host"),
|
|
CustomLink: gu.Ptr("https://host"),
|
|
CustomLinkText: gu.Ptr("linktext"),
|
|
},
|
|
}
|
|
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
wantRowsAffected int64
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "incomplete condition",
|
|
condition: repo.InstanceIDCondition(instanceID),
|
|
wantRowsAffected: 0,
|
|
wantErr: database.NewMissingConditionError(repo.IDColumn()),
|
|
},
|
|
{
|
|
name: "not found",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeLegalAndSupport, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLegalAndSupport, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeLegalAndSupport, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLegalAndSupport, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeLegalAndSupport, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
|
|
require.ErrorIs(t, err, tt.wantErr)
|
|
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
|
|
})
|
|
}
|
|
}
|