mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:57:32 +00:00

# Which Problems Are Solved Currently the username uniqueness is on instance level, we want to achieve a way to set it at organization level. # How the Problems Are Solved Addition of endpoints and a resource on organization level, where this setting can be managed. If nothing it set, the uniqueness is expected to be at instance level, where only users with instance permissions should be able to change this setting. # Additional Changes None # Additional Context Includes #10086 Closes #9964 --------- Co-authored-by: Marco A. <marco@zitadel.com>
253 lines
9.9 KiB
Go
253 lines
9.9 KiB
Go
package settings
|
|
|
|
import (
|
|
"time"
|
|
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/query"
|
|
settings "github.com/zitadel/zitadel/pkg/grpc/settings/v2beta"
|
|
)
|
|
|
|
func loginSettingsToPb(current *query.LoginPolicy) *settings.LoginSettings {
|
|
multi := make([]settings.MultiFactorType, len(current.MultiFactors))
|
|
for i, typ := range current.MultiFactors {
|
|
multi[i] = multiFactorTypeToPb(typ)
|
|
}
|
|
second := make([]settings.SecondFactorType, len(current.SecondFactors))
|
|
for i, typ := range current.SecondFactors {
|
|
second[i] = secondFactorTypeToPb(typ)
|
|
}
|
|
|
|
return &settings.LoginSettings{
|
|
AllowUsernamePassword: current.AllowUsernamePassword,
|
|
AllowRegister: current.AllowRegister,
|
|
AllowExternalIdp: current.AllowExternalIDPs,
|
|
ForceMfa: current.ForceMFA,
|
|
ForceMfaLocalOnly: current.ForceMFALocalOnly,
|
|
PasskeysType: passkeysTypeToPb(current.PasswordlessType),
|
|
HidePasswordReset: current.HidePasswordReset,
|
|
IgnoreUnknownUsernames: current.IgnoreUnknownUsernames,
|
|
AllowDomainDiscovery: current.AllowDomainDiscovery,
|
|
DisableLoginWithEmail: current.DisableLoginWithEmail,
|
|
DisableLoginWithPhone: current.DisableLoginWithPhone,
|
|
DefaultRedirectUri: current.DefaultRedirectURI,
|
|
PasswordCheckLifetime: durationpb.New(time.Duration(current.PasswordCheckLifetime)),
|
|
ExternalLoginCheckLifetime: durationpb.New(time.Duration(current.ExternalLoginCheckLifetime)),
|
|
MfaInitSkipLifetime: durationpb.New(time.Duration(current.MFAInitSkipLifetime)),
|
|
SecondFactorCheckLifetime: durationpb.New(time.Duration(current.SecondFactorCheckLifetime)),
|
|
MultiFactorCheckLifetime: durationpb.New(time.Duration(current.MultiFactorCheckLifetime)),
|
|
SecondFactors: second,
|
|
MultiFactors: multi,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
}
|
|
}
|
|
|
|
func isDefaultToResourceOwnerTypePb(isDefault bool) settings.ResourceOwnerType {
|
|
if isDefault {
|
|
return settings.ResourceOwnerType_RESOURCE_OWNER_TYPE_INSTANCE
|
|
}
|
|
return settings.ResourceOwnerType_RESOURCE_OWNER_TYPE_ORG
|
|
}
|
|
|
|
func passkeysTypeToPb(passwordlessType domain.PasswordlessType) settings.PasskeysType {
|
|
switch passwordlessType {
|
|
case domain.PasswordlessTypeAllowed:
|
|
return settings.PasskeysType_PASSKEYS_TYPE_ALLOWED
|
|
case domain.PasswordlessTypeNotAllowed:
|
|
return settings.PasskeysType_PASSKEYS_TYPE_NOT_ALLOWED
|
|
default:
|
|
return settings.PasskeysType_PASSKEYS_TYPE_NOT_ALLOWED
|
|
}
|
|
}
|
|
|
|
func secondFactorTypeToPb(secondFactorType domain.SecondFactorType) settings.SecondFactorType {
|
|
switch secondFactorType {
|
|
case domain.SecondFactorTypeTOTP:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP
|
|
case domain.SecondFactorTypeU2F:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F
|
|
case domain.SecondFactorTypeOTPEmail:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL
|
|
case domain.SecondFactorTypeOTPSMS:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS
|
|
case domain.SecondFactorTypeUnspecified:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED
|
|
default:
|
|
return settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func multiFactorTypeToPb(typ domain.MultiFactorType) settings.MultiFactorType {
|
|
switch typ {
|
|
case domain.MultiFactorTypeU2FWithPIN:
|
|
return settings.MultiFactorType_MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION
|
|
case domain.MultiFactorTypeUnspecified:
|
|
return settings.MultiFactorType_MULTI_FACTOR_TYPE_UNSPECIFIED
|
|
default:
|
|
return settings.MultiFactorType_MULTI_FACTOR_TYPE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func passwordComplexitySettingsToPb(current *query.PasswordComplexityPolicy) *settings.PasswordComplexitySettings {
|
|
return &settings.PasswordComplexitySettings{
|
|
MinLength: current.MinLength,
|
|
RequiresUppercase: current.HasUppercase,
|
|
RequiresLowercase: current.HasLowercase,
|
|
RequiresNumber: current.HasNumber,
|
|
RequiresSymbol: current.HasSymbol,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
}
|
|
}
|
|
|
|
func passwordExpirySettingsToPb(current *query.PasswordAgePolicy) *settings.PasswordExpirySettings {
|
|
return &settings.PasswordExpirySettings{
|
|
MaxAgeDays: current.MaxAgeDays,
|
|
ExpireWarnDays: current.ExpireWarnDays,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
}
|
|
}
|
|
|
|
func brandingSettingsToPb(current *query.LabelPolicy, assetPrefix string) *settings.BrandingSettings {
|
|
return &settings.BrandingSettings{
|
|
LightTheme: themeToPb(current.Light, assetPrefix, current.ResourceOwner),
|
|
DarkTheme: themeToPb(current.Dark, assetPrefix, current.ResourceOwner),
|
|
FontUrl: domain.AssetURL(assetPrefix, current.ResourceOwner, current.FontURL),
|
|
DisableWatermark: current.WatermarkDisabled,
|
|
HideLoginNameSuffix: current.HideLoginNameSuffix,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
ThemeMode: themeModeToPb(current.ThemeMode),
|
|
}
|
|
}
|
|
|
|
func themeModeToPb(themeMode domain.LabelPolicyThemeMode) settings.ThemeMode {
|
|
switch themeMode {
|
|
case domain.LabelPolicyThemeAuto:
|
|
return settings.ThemeMode_THEME_MODE_AUTO
|
|
case domain.LabelPolicyThemeLight:
|
|
return settings.ThemeMode_THEME_MODE_LIGHT
|
|
case domain.LabelPolicyThemeDark:
|
|
return settings.ThemeMode_THEME_MODE_DARK
|
|
default:
|
|
return settings.ThemeMode_THEME_MODE_AUTO
|
|
}
|
|
}
|
|
|
|
func themeToPb(theme query.Theme, assetPrefix, resourceOwner string) *settings.Theme {
|
|
return &settings.Theme{
|
|
PrimaryColor: theme.PrimaryColor,
|
|
BackgroundColor: theme.BackgroundColor,
|
|
FontColor: theme.FontColor,
|
|
WarnColor: theme.WarnColor,
|
|
LogoUrl: domain.AssetURL(assetPrefix, resourceOwner, theme.LogoURL),
|
|
IconUrl: domain.AssetURL(assetPrefix, resourceOwner, theme.IconURL),
|
|
}
|
|
}
|
|
|
|
func domainSettingsToPb(current *query.DomainPolicy) *settings.DomainSettings {
|
|
return &settings.DomainSettings{
|
|
LoginNameIncludesDomain: current.UserLoginMustBeDomain,
|
|
RequireOrgDomainVerification: current.ValidateOrgDomains,
|
|
SmtpSenderAddressMatchesInstanceDomain: current.SMTPSenderAddressMatchesInstanceDomain,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
}
|
|
}
|
|
|
|
func legalAndSupportSettingsToPb(current *query.PrivacyPolicy) *settings.LegalAndSupportSettings {
|
|
return &settings.LegalAndSupportSettings{
|
|
TosLink: current.TOSLink,
|
|
PrivacyPolicyLink: current.PrivacyLink,
|
|
HelpLink: current.HelpLink,
|
|
SupportEmail: string(current.SupportEmail),
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
DocsLink: current.DocsLink,
|
|
CustomLink: current.CustomLink,
|
|
CustomLinkText: current.CustomLinkText,
|
|
}
|
|
}
|
|
|
|
func lockoutSettingsToPb(current *query.LockoutPolicy) *settings.LockoutSettings {
|
|
return &settings.LockoutSettings{
|
|
MaxPasswordAttempts: current.MaxPasswordAttempts,
|
|
MaxOtpAttempts: current.MaxOTPAttempts,
|
|
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
|
|
}
|
|
}
|
|
|
|
func identityProvidersToPb(idps []*query.IDPLoginPolicyLink) []*settings.IdentityProvider {
|
|
providers := make([]*settings.IdentityProvider, len(idps))
|
|
for i, idp := range idps {
|
|
providers[i] = identityProviderToPb(idp)
|
|
}
|
|
return providers
|
|
}
|
|
|
|
func identityProviderToPb(idp *query.IDPLoginPolicyLink) *settings.IdentityProvider {
|
|
return &settings.IdentityProvider{
|
|
Id: idp.IDPID,
|
|
Name: domain.IDPName(idp.IDPName, idp.IDPType),
|
|
Type: idpTypeToPb(idp.IDPType),
|
|
}
|
|
}
|
|
|
|
func idpTypeToPb(idpType domain.IDPType) settings.IdentityProviderType {
|
|
switch idpType {
|
|
case domain.IDPTypeUnspecified:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_UNSPECIFIED
|
|
case domain.IDPTypeOIDC:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_OIDC
|
|
case domain.IDPTypeJWT:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_JWT
|
|
case domain.IDPTypeOAuth:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_OAUTH
|
|
case domain.IDPTypeLDAP:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_LDAP
|
|
case domain.IDPTypeAzureAD:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_AZURE_AD
|
|
case domain.IDPTypeGitHub:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_GITHUB
|
|
case domain.IDPTypeGitHubEnterprise:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_GITHUB_ES
|
|
case domain.IDPTypeGitLab:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_GITLAB
|
|
case domain.IDPTypeGitLabSelfHosted:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_GITLAB_SELF_HOSTED
|
|
case domain.IDPTypeGoogle:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_GOOGLE
|
|
case domain.IDPTypeSAML:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_SAML
|
|
case domain.IDPTypeApple:
|
|
// Handle all remaining cases so the linter succeeds
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_UNSPECIFIED
|
|
default:
|
|
return settings.IdentityProviderType_IDENTITY_PROVIDER_TYPE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func securityPolicyToSettingsPb(policy *query.SecurityPolicy) *settings.SecuritySettings {
|
|
return &settings.SecuritySettings{
|
|
EmbeddedIframe: &settings.EmbeddedIframeSettings{
|
|
Enabled: policy.EnableIframeEmbedding,
|
|
AllowedOrigins: policy.AllowedOrigins,
|
|
},
|
|
EnableImpersonation: policy.EnableImpersonation,
|
|
}
|
|
}
|
|
|
|
func securitySettingsToCommand(req *settings.SetSecuritySettingsRequest) *command.SecurityPolicy {
|
|
return &command.SecurityPolicy{
|
|
EnableIframeEmbedding: req.GetEmbeddedIframe().GetEnabled(),
|
|
AllowedOrigins: req.GetEmbeddedIframe().GetAllowedOrigins(),
|
|
EnableImpersonation: req.GetEnableImpersonation(),
|
|
}
|
|
}
|
|
|
|
func organizationSettingsToCommand(req *settings.SetOrganizationSettingsRequest) *command.SetOrganizationSettings {
|
|
return &command.SetOrganizationSettings{
|
|
OrganizationID: req.OrganizationId,
|
|
OrganizationScopedUsernames: req.OrganizationScopedUsernames,
|
|
}
|
|
}
|