mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
# Which Problems Are Solved Zitadel exposes the secrets generator configuration through its admin api. This allows instance admins to manage them on their own and they can create overwrite the system / runtime defaults (incl. expiration). This very much needed in multi-instance scenarios such as zitadel.cloud. Currently the invite code configuration was not manageable through the API, but only runtime config. # How the Problems Are Solved - added the `invite_code` type to the API allowing it to be set and retrieved. - added the type to console's management list - added the type to be stored on instance setup - change the `GetSecretGenerator` endpoint to fall back to the runtime config if no config is stored on the instance itself - ensure the `length` and at least one charset is enabled, return an error otherwise - expiry is not enforced, so 0 allows codes with no expiry (current state) # Additional Changes None # Additional Context - closes https://github.com/zitadel/zitadel/issues/10474
5181 lines
162 KiB
Go
5181 lines
162 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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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: repo.UniqueCondition(
|
|
existingInstanceSettings.InstanceID,
|
|
nil,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "activate organization",
|
|
condition: repo.UniqueCondition(
|
|
existingInstanceSettings.InstanceID,
|
|
existingOrganizationSettings.OrganizationID,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
condition: repo.UniqueCondition(
|
|
"foo",
|
|
nil,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
wantRowsAffected: 0,
|
|
},
|
|
|
|
{
|
|
name: "non-existing organization",
|
|
condition: repo.UniqueCondition(
|
|
existingInstanceSettings.InstanceID,
|
|
gu.Ptr("foo"),
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
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: repo.UniqueCondition(
|
|
existingInstanceSettings.InstanceID,
|
|
nil,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "activate organization",
|
|
condition: repo.UniqueCondition(
|
|
existingOrganizationSettings.InstanceID,
|
|
existingOrganizationSettings.OrganizationID,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
condition: repo.UniqueCondition(
|
|
"foo",
|
|
nil,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
updatedAt: time.Now(),
|
|
wantRowsAffected: 0,
|
|
},
|
|
|
|
{
|
|
name: "non-existing organization",
|
|
condition: repo.UniqueCondition(
|
|
existingOrganizationSettings.InstanceID,
|
|
gu.Ptr("foo"),
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
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,
|
|
repo.UniqueCondition(
|
|
existingInstanceSettings.InstanceID,
|
|
existingInstanceSettings.OrganizationID,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
)
|
|
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,
|
|
repo.UniqueCondition(
|
|
existingOrganizationSettings.InstanceID,
|
|
existingOrganizationSettings.OrganizationID,
|
|
domain.SettingTypeBranding,
|
|
domain.SettingStatePreview,
|
|
),
|
|
)
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSecretGeneratorSettings(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.SecretGeneratorSettingsRepository()
|
|
|
|
settings := []*domain.SecretGeneratorSettings{
|
|
createSecretGeneratorSettings(firstInstanceID, nil),
|
|
createSecretGeneratorSettings(secondInstanceID, nil),
|
|
createSecretGeneratorSettings(firstInstanceID, gu.Ptr(firstOrgID)),
|
|
createSecretGeneratorSettings(secondInstanceID, gu.Ptr(secondOrgID)),
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want *domain.SecretGeneratorSettings
|
|
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 TestListSecretGeneratorSettings(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.SecretGeneratorSettingsRepository()
|
|
|
|
settings := []*domain.SecretGeneratorSettings{
|
|
createSecretGeneratorSettings(firstInstanceID, nil),
|
|
createSecretGeneratorSettings(secondInstanceID, nil),
|
|
createSecretGeneratorSettings(firstInstanceID, gu.Ptr(firstOrgID)),
|
|
createSecretGeneratorSettings(secondInstanceID, gu.Ptr(secondOrgID)),
|
|
}
|
|
|
|
for _, setting := range settings {
|
|
err := repo.Set(t.Context(), tx, setting)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
condition database.Condition
|
|
want []*domain.SecretGeneratorSettings
|
|
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.SecretGeneratorSettings{},
|
|
},
|
|
{
|
|
name: "all from instance",
|
|
condition: repo.InstanceIDCondition(firstInstanceID),
|
|
want: []*domain.SecretGeneratorSettings{settings[2], settings[0]},
|
|
},
|
|
{
|
|
name: "only from instance",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(nil),
|
|
),
|
|
want: []*domain.SecretGeneratorSettings{settings[0]},
|
|
},
|
|
{
|
|
name: "all from first org",
|
|
condition: database.And(
|
|
repo.InstanceIDCondition(firstInstanceID),
|
|
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
|
|
),
|
|
want: []*domain.SecretGeneratorSettings{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 TestSetSecretGeneratorSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.SecretGeneratorSettingsRepository()
|
|
|
|
existingSettings := createSecretGeneratorSettings(instanceID, gu.Ptr(orgID))
|
|
|
|
err := repo.Set(t.Context(), tx, existingSettings)
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
settings *domain.SecretGeneratorSettings
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "create instance",
|
|
settings: createSecretGeneratorSettings(instanceID, nil),
|
|
},
|
|
{
|
|
name: "update organization",
|
|
settings: createSecretGeneratorSettings(instanceID, gu.Ptr(orgID)),
|
|
},
|
|
{
|
|
name: "non-existing instance",
|
|
settings: createSecretGeneratorSettings("foo", nil),
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "non-existing org",
|
|
settings: createSecretGeneratorSettings(instanceID, gu.Ptr("foo")),
|
|
wantErr: new(database.ForeignKeyError),
|
|
},
|
|
{
|
|
name: "nil settings",
|
|
settings: nil,
|
|
wantErr: database.ErrInvalidChangeTarget,
|
|
},
|
|
}
|
|
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 TestDeleteSecretGeneratorSettings(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
orgID := createOrganization(t, tx, instanceID)
|
|
repo := repository.SecretGeneratorSettingsRepository()
|
|
|
|
existingInstanceSettings := createSecretGeneratorSettings(instanceID, nil)
|
|
err := repo.Set(t.Context(), tx, existingInstanceSettings)
|
|
require.NoError(t, err)
|
|
|
|
existingOrganizationSettings := createSecretGeneratorSettings(instanceID, gu.Ptr(orgID))
|
|
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.SettingTypeSecretGenerator, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete instance",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete instance twice",
|
|
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
|
|
wantRowsAffected: 0,
|
|
},
|
|
{
|
|
name: "delete organization",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
|
|
wantRowsAffected: 1,
|
|
},
|
|
{
|
|
name: "delete organization twice",
|
|
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecretGenerator, 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 createDefaultSecretGeneratorAttrs() domain.SecretGeneratorAttrs {
|
|
return domain.SecretGeneratorAttrs{
|
|
Length: gu.Ptr(uint(32)),
|
|
IncludeUpperLetters: gu.Ptr(true),
|
|
IncludeLowerLetters: gu.Ptr(true),
|
|
IncludeDigits: gu.Ptr(true),
|
|
IncludeSymbols: gu.Ptr(false),
|
|
}
|
|
}
|
|
|
|
func createDefaultSecretGeneratorAttrsWithExpiry(expiry time.Duration) domain.SecretGeneratorAttrsWithExpiry {
|
|
return domain.SecretGeneratorAttrsWithExpiry{
|
|
Expiry: gu.Ptr(expiry),
|
|
SecretGeneratorAttrs: domain.SecretGeneratorAttrs{
|
|
Length: gu.Ptr(uint(32)),
|
|
IncludeUpperLetters: gu.Ptr(true),
|
|
IncludeLowerLetters: gu.Ptr(true),
|
|
IncludeDigits: gu.Ptr(true),
|
|
IncludeSymbols: gu.Ptr(false),
|
|
},
|
|
}
|
|
}
|
|
|
|
func createDefaultSecretGeneratorSettingsAttributes() domain.SecretGeneratorSettingsAttributes {
|
|
attrs := createDefaultSecretGeneratorAttrs()
|
|
oneDay := 24 * time.Hour
|
|
thirtyMinutes := 30 * time.Minute
|
|
tenMinutes := 10 * time.Minute
|
|
|
|
return domain.SecretGeneratorSettingsAttributes{
|
|
ClientSecret: &domain.ClientSecretAttributes{
|
|
SecretGeneratorAttrs: attrs,
|
|
},
|
|
InitializeUserCode: &domain.InitializeUserCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(oneDay),
|
|
},
|
|
EmailVerificationCode: &domain.EmailVerificationCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
|
|
},
|
|
PhoneVerificationCode: &domain.PhoneVerificationCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
|
|
},
|
|
PasswordVerificationCode: &domain.PasswordVerificationCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
|
|
},
|
|
PasswordlessInitCode: &domain.PasswordlessInitCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(tenMinutes),
|
|
},
|
|
DomainVerification: &domain.DomainVerificationAttributes{
|
|
SecretGeneratorAttrs: attrs,
|
|
},
|
|
OTPSMS: &domain.OTPSMSAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
|
|
},
|
|
OTPEmail: &domain.OTPEmailAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
|
|
},
|
|
InviteCode: &domain.InviteCodeAttributes{
|
|
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(oneDay * 3),
|
|
},
|
|
}
|
|
}
|
|
|
|
func createSecretGeneratorSettings(instanceID string, organizationID *string) *domain.SecretGeneratorSettings {
|
|
return &domain.SecretGeneratorSettings{
|
|
Settings: domain.Settings{
|
|
InstanceID: instanceID,
|
|
OrganizationID: organizationID,
|
|
},
|
|
SecretGeneratorSettingsAttributes: createDefaultSecretGeneratorSettingsAttributes(),
|
|
}
|
|
}
|
|
|
|
func TestSecretGeneratorSettingsInviteCodeRoundTrip(t *testing.T) {
|
|
tx, rollback := transactionForRollback(t)
|
|
defer rollback()
|
|
|
|
instanceID := createInstance(t, tx)
|
|
repo := repository.SecretGeneratorSettingsRepository()
|
|
|
|
want := createSecretGeneratorSettings(instanceID, nil)
|
|
require.NotNil(t, want.InviteCode)
|
|
|
|
err := repo.Set(t.Context(), tx, want)
|
|
require.NoError(t, err)
|
|
|
|
got, err := repo.Get(t.Context(), tx, database.WithCondition(
|
|
repo.UniqueCondition(instanceID, nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
|
|
))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, got.InviteCode)
|
|
assert.EqualExportedValues(t, want.InviteCode, got.InviteCode)
|
|
|
|
list, err := repo.List(t.Context(), tx, database.WithCondition(
|
|
repo.InstanceIDCondition(instanceID),
|
|
))
|
|
require.NoError(t, err)
|
|
require.Len(t, list, 1)
|
|
require.NotNil(t, list[0].InviteCode)
|
|
assert.EqualExportedValues(t, want.InviteCode, list[0].InviteCode)
|
|
}
|