mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 16:17:23 +00:00
feat: allow domain discovery for unknown usernames (#4484)
* fix: wait for projection initialization to be done * feat: allow domain discovery for unknown usernames * fix linting * Update console/src/assets/i18n/de.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/en.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/it.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * Update console/src/assets/i18n/fr.json Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> * fix zh i18n text * fix projection table name Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com>
This commit is contained in:
parent
ce22961d8e
commit
bffb10a4b4
@ -399,6 +399,7 @@ DefaultInstance:
|
||||
ForceMFA: false
|
||||
HidePasswordReset: false
|
||||
IgnoreUnknownUsernames: false
|
||||
AllowDomainDiscovery: false
|
||||
PasswordlessType: 1 #1: allowed 0: not allowed
|
||||
DefaultRedirectURI: #empty because we use the Console UI
|
||||
PasswordCheckLifetime: 240h #10d
|
||||
|
@ -271,6 +271,7 @@ export class IdpTableComponent implements OnInit {
|
||||
.setNanos(this.loginPolicy.multiFactorCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(this.loginPolicy.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginPolicy.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginPolicy.defaultRedirectUri);
|
||||
|
||||
|
@ -285,6 +285,28 @@
|
||||
</ng-template> -->
|
||||
</div>
|
||||
|
||||
<div class="login-policy-row">
|
||||
<mat-checkbox
|
||||
class="login-policy-toggle"
|
||||
color="primary"
|
||||
ngDefaultControl
|
||||
[(ngModel)]="loginData.allowDomainDiscovery"
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'policy.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
>
|
||||
{{ 'POLICY.DATA.ALLOWDOMAINDISCOVERY' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="login-policy-row">
|
||||
<mat-checkbox
|
||||
class="login-policy-toggle"
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
import {
|
||||
AddCustomLoginPolicyRequest,
|
||||
GetLoginPolicyResponse as MgmtGetLoginPolicyResponse,
|
||||
UpdateCustomLoginPolicyRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { LoginPolicy, PasswordlessType } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
@ -144,37 +145,65 @@ export class LoginPolicyComponent implements OnInit {
|
||||
if (this.loginData) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(this.loginData.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(this.loginData.secondFactorsList);
|
||||
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
if (this.isDefault) {
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(this.loginData.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(this.loginData.secondFactorsList);
|
||||
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as ManagementService).addCustomLoginPolicy(mgmtreq);
|
||||
} else {
|
||||
const mgmtreq = new UpdateCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as ManagementService).updateCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
@ -200,6 +229,7 @@ export class LoginPolicyComponent implements OnInit {
|
||||
|
||||
const admin_mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setMultiFactorCheckLifetime(admin_mficl);
|
||||
adminreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery);
|
||||
adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
adminreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
|
@ -1176,6 +1176,8 @@
|
||||
"HIDELOGINNAMESUFFIX": "Loginname Suffix ausblenden",
|
||||
"IGNOREUNKNOWNUSERNAMES": "Unbekannte Usernamen ignorieren",
|
||||
"IGNOREUNKNOWNUSERNAMES_DESC": "Ist die Option gewählt, wird der Passwort Schritt im Login auch angezeigt wenn der User nicht gefunden wurde. Dem Benutzer wird auf bei der Passwortprüfung nicht angezeigt ob der Username oder das Passwort falsch war.",
|
||||
"ALLOWDOMAINDISCOVERY": "Domänenentdeckung erlauben",
|
||||
"ALLOWDOMAINDISCOVERY_DESC": "Ist die Option gewählt, wird die Endung (@domain.com) eines unbekannten Benutzernamens im Login mit den Organisationsdomänen verglichen. Bei Übereinstimmung wird der Benutzer auf die Registrierung dieser Organisation weitergeleitet.",
|
||||
"DEFAULTREDIRECTURI": "Default Redirect URI",
|
||||
"DEFAULTREDIRECTURI_DESC": "Definiert, wohin der Benutzer umgeleitet wird, wenn die Anmeldung ohne App-Kontext gestartet wurde (z. B. von Mail)",
|
||||
"ERRORMSGPOPUP": "Fehler als Dialog Fenster",
|
||||
|
@ -1176,6 +1176,8 @@
|
||||
"HIDELOGINNAMESUFFIX": "Hide Loginname suffix",
|
||||
"IGNOREUNKNOWNUSERNAMES": "Ignore unknown usernames",
|
||||
"IGNOREUNKNOWNUSERNAMES_DESC": "If the option is selected, the password screen will be displayed in the login process even if the user was not found. The error on the password check will not disclose if the username or password was wrong.",
|
||||
"ALLOWDOMAINDISCOVERY": "Domain discovery allowed",
|
||||
"ALLOWDOMAINDISCOVERY_DESC": "If the option is selected, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the organization domains and will redirect to the registration of that organisation on success.",
|
||||
"DEFAULTREDIRECTURI": "Default Redirect URI",
|
||||
"DEFAULTREDIRECTURI_DESC": "Defines where the user will be redirected to if the login has started without an app context (e.g. from mail)",
|
||||
"ERRORMSGPOPUP": "Show Error in Dialog",
|
||||
|
@ -1176,6 +1176,8 @@
|
||||
"HIDELOGINNAMESUFFIX": "Masquer le suffixe du nom de connexion",
|
||||
"IGNOREUNKNOWNUSERNAMES": "Ignorer les noms d'utilisateur inconnus",
|
||||
"IGNOREUNKNOWNUSERNAMES_DESC": "Si l'option est sélectionnée, l'écran du mot de passe sera affiché dans le processus de connexion même si l'utilisateur n'a pas été trouvé. L'erreur sur la vérification du mot de passe ne révélera pas si le nom d'utilisateur ou le mot de passe était erroné.",
|
||||
"ALLOWDOMAINDISCOVERY": "Découverte du domaine autorisée",
|
||||
"ALLOWDOMAINDISCOVERY_DESC": "Si l'option est sélectionnée, le suffixe (@domain.com) d'un nom d'utilisateur inconnu saisi sur l'écran de connexion sera comparé aux domaines organisation et redirigera vers l'enregistrement de cette organisation en cas de succès.",
|
||||
"DEFAULTREDIRECTURI": "URI de redirection par défaut",
|
||||
"DEFAULTREDIRECTURI_DESC": "Définit l'endroit où l'utilisateur sera redirigé si la connexion a commencé sans contexte d'application (par exemple, à partir du courrier électronique).",
|
||||
"ERRORMSGPOPUP": "Afficher l'erreur dans la boîte de dialogue",
|
||||
|
@ -1176,6 +1176,8 @@
|
||||
"HIDELOGINNAMESUFFIX": "Nascondi il suffisso del nome utente",
|
||||
"IGNOREUNKNOWNUSERNAMES": "Ignora un nome utente sconosciuto",
|
||||
"IGNOREUNKNOWNUSERNAMES_DESC": "Se l'opzione \u00e8 selezionata, l'inserimento della password viene mostrato anche se nessun utente è stato trovato. Nota che dopo il controllo della password, non viene mostrato se il nome utente o la password erano errati.",
|
||||
"ALLOWDOMAINDISCOVERY": "Scoperta del dominio consentita",
|
||||
"ALLOWDOMAINDISCOVERY_DESC": "Se l'opzione è selezionata, il suffisso (@domain.com) di un nome utente sconosciuto inserito nel login verrà confrontato con i domini organizzazione e, in caso di successo, verrà reindirizzato alla registrazione di tale organizzazione",
|
||||
"DEFAULTREDIRECTURI": "Default Redirect URI",
|
||||
"DEFAULTREDIRECTURI_DESC": "Definisce dove verrà reindirizzato l'utente se l'accesso è stato avviato senza un contesto dell'app (ad es. dall' email)",
|
||||
"ERRORMSGPOPUP": "Mostra l'errore nella finestra di dialogo",
|
||||
|
@ -1175,6 +1175,8 @@
|
||||
"HIDELOGINNAMESUFFIX": "隐藏登录名后缀",
|
||||
"IGNOREUNKNOWNUSERNAMES": "忽略未知用户名",
|
||||
"IGNOREUNKNOWNUSERNAMES_DESC": "如果选择该选项,即使未找到用户,登录过程中也会显示密码屏幕。如果用户名或密码错误,密码检查的错误不会透露。",
|
||||
"ALLOWDOMAINDISCOVERY": "允许域名发现",
|
||||
"ALLOWDOMAINDISCOVERY_DESC": "如果选择该选项,在登录屏幕上输入的未知用户名的后缀(@domain.com)将与组织的域名进行匹配,成功后将重定向到组织的注册。",
|
||||
"DEFAULTREDIRECTURI": "默认重定向 URI",
|
||||
"DEFAULTREDIRECTURI_DESC": "定义如果在没有应用程序上下文的情况下开始登录(例如来自邮件),用户将被重定向到哪里。",
|
||||
"ERRORMSGPOPUP": "在对话框中显示错误",
|
||||
|
@ -4359,6 +4359,7 @@ this is en empty request
|
||||
| mfa_init_skip_lifetime | google.protobuf.Duration | - | |
|
||||
| second_factor_check_lifetime | google.protobuf.Duration | - | |
|
||||
| multi_factor_check_lifetime | google.protobuf.Duration | - | |
|
||||
| allow_domain_discovery | bool | If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success. | |
|
||||
|
||||
|
||||
|
||||
|
@ -3091,7 +3091,7 @@ This is an empty request
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| primary_color | string | - | string.max_len: 50<br /> |
|
||||
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes | |
|
||||
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set | |
|
||||
| warn_color | string | - | string.max_len: 50<br /> |
|
||||
| background_color | string | - | string.max_len: 50<br /> |
|
||||
| font_color | string | - | string.max_len: 50<br /> |
|
||||
@ -3159,6 +3159,7 @@ This is an empty request
|
||||
| second_factors | repeated zitadel.policy.v1.SecondFactorType | - | |
|
||||
| multi_factors | repeated zitadel.policy.v1.MultiFactorType | - | |
|
||||
| idps | repeated AddCustomLoginPolicyRequest.IDP | - | |
|
||||
| allow_domain_discovery | bool | If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success. | |
|
||||
|
||||
|
||||
|
||||
@ -8106,6 +8107,7 @@ This is an empty request
|
||||
| mfa_init_skip_lifetime | google.protobuf.Duration | - | |
|
||||
| second_factor_check_lifetime | google.protobuf.Duration | - | |
|
||||
| multi_factor_check_lifetime | google.protobuf.Duration | - | |
|
||||
| allow_domain_discovery | bool | If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success. | |
|
||||
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ title: zitadel/policy.proto
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
| primary_color | string | hex value for primary color | |
|
||||
| is_default | bool | defines if the organisation's admin changed the policy | |
|
||||
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes | |
|
||||
| hide_login_name_suffix | bool | hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set | |
|
||||
| warn_color | string | hex value for secondary color | |
|
||||
| background_color | string | hex value for background color | |
|
||||
| font_color | string | hex value for font color | |
|
||||
@ -88,6 +88,7 @@ title: zitadel/policy.proto
|
||||
| second_factors | repeated SecondFactorType | - | |
|
||||
| multi_factors | repeated MultiFactorType | - | |
|
||||
| idps | repeated zitadel.idp.v1.IDPLoginPolicyLink | - | |
|
||||
| allow_domain_discovery | bool | If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success. | |
|
||||
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.Log
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@ -26,7 +26,7 @@ func (s *Server) GetMyOrg(ctx context.Context, req *mgmt_pb.GetMyOrgRequest) (*m
|
||||
}
|
||||
|
||||
func (s *Server) GetOrgByDomainGlobal(ctx context.Context, req *mgmt_pb.GetOrgByDomainGlobalRequest) (*mgmt_pb.GetOrgByDomainGlobalResponse, error) {
|
||||
org, err := s.query.OrgByDomainGlobal(ctx, req.Domain)
|
||||
org, err := s.query.OrgByPrimaryDomain(ctx, req.Domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ func AddLoginPolicyToDomain(p *mgmt_pb.AddCustomLoginPolicyRequest) *domain.Logi
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
@ -49,6 +50,7 @@ func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domai
|
||||
PasswordlessType: policy_grpc.PasswordlessTypeToDomain(p.PasswordlessType),
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@ -21,6 +21,7 @@ func ModelLoginPolicyToPb(policy *query.LoginPolicy) *policy_pb.LoginPolicy {
|
||||
PasswordlessType: ModelPasswordlessTypeToPb(policy.PasswordlessType),
|
||||
HidePasswordReset: policy.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: policy.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: policy.AllowDomainDiscovery,
|
||||
DefaultRedirectUri: policy.DefaultRedirectURI,
|
||||
PasswordCheckLifetime: durationpb.New(policy.PasswordCheckLifetime),
|
||||
ExternalLoginCheckLifetime: durationpb.New(policy.ExternalLoginCheckLifetime),
|
||||
|
@ -91,7 +91,7 @@ func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string
|
||||
scope := scopes[i]
|
||||
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
|
||||
var orgID string
|
||||
org, err := o.query.OrgByDomainGlobal(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
|
||||
if err == nil {
|
||||
orgID = org.ID
|
||||
}
|
||||
|
@ -59,11 +59,15 @@ func (l *Login) handleExternalRegister(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
l.handleExternalRegisterByConfigID(w, r, authReq, data.IDPConfigID)
|
||||
}
|
||||
|
||||
func (l *Login) handleExternalRegisterByConfigID(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, configID string) {
|
||||
if authReq == nil {
|
||||
l.defaultRedirect(w, r)
|
||||
return
|
||||
}
|
||||
idpConfig, err := l.getIDPConfigByID(r, data.IDPConfigID)
|
||||
idpConfig, err := l.getIDPConfigByID(r, configID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
|
@ -33,12 +33,29 @@ func (l *Login) renderRegisterOption(w http.ResponseWriter, r *http.Request, aut
|
||||
if err != nil {
|
||||
errID, errMessage = l.getErrorMessage(r, err)
|
||||
}
|
||||
allowed := registrationAllowed(authReq)
|
||||
externalAllowed := externalRegistrationAllowed(authReq)
|
||||
if err == nil {
|
||||
// if only external allowed with a single idp then use that
|
||||
if !allowed && externalAllowed && len(authReq.AllowedExternalIDPs) == 1 {
|
||||
l.handleExternalRegisterByConfigID(w, r, authReq, authReq.AllowedExternalIDPs[0].IDPConfigID)
|
||||
return
|
||||
}
|
||||
// if only direct registration is allowed, show the form
|
||||
if allowed && !externalAllowed {
|
||||
l.renderRegister(w, r, authReq, nil, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
data := registerOptionData{
|
||||
baseData: l.getBaseData(r, authReq, "RegisterOption", errID, errMessage),
|
||||
}
|
||||
funcs := map[string]interface{}{
|
||||
"hasRegistration": func() bool {
|
||||
return allowed
|
||||
},
|
||||
"hasExternalLogin": func() bool {
|
||||
return authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
return externalAllowed
|
||||
},
|
||||
}
|
||||
translator := l.getTranslator(r.Context(), authReq)
|
||||
@ -58,3 +75,11 @@ func (l *Login) handleRegisterOptionCheck(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
l.handleRegisterOption(w, r)
|
||||
}
|
||||
|
||||
func registrationAllowed(authReq *domain.AuthRequest) bool {
|
||||
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowRegister
|
||||
}
|
||||
|
||||
func externalRegistrationAllowed(authReq *domain.AuthRequest) bool {
|
||||
return authReq != nil && authReq.LoginPolicy != nil && authReq.LoginPolicy.AllowExternalIDP && authReq.AllowedExternalIDPs != nil && len(authReq.AllowedExternalIDPs) > 0
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="lgn-register-options">
|
||||
{{if .LoginPolicy.AllowUsernamePassword }}
|
||||
{{if hasRegistration }}
|
||||
<button class="lgn-raised-button lgn-primary" name="usernamepassword" value="true"
|
||||
formnovalidate>{{t "RegisterOption.RegisterUsernamePasswordButtonText"}}</button>
|
||||
{{end}}
|
||||
@ -42,4 +42,4 @@
|
||||
<script src="{{ resourceUrl "scripts/form_submit.js" }}"></script>
|
||||
<script src="{{ resourceUrl "scripts/default_form_validation.js" }}"></script>
|
||||
|
||||
{{template "main-bottom" .}}
|
||||
{{template "main-bottom" .}}
|
||||
|
@ -93,7 +93,7 @@ type userCommandProvider interface {
|
||||
|
||||
type orgViewProvider interface {
|
||||
OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
OrgByDomainGlobal(context.Context, string) (*query.Org, error)
|
||||
OrgByPrimaryDomain(context.Context, string) (*query.Org, error)
|
||||
}
|
||||
|
||||
type userGrantProvider interface {
|
||||
@ -651,23 +651,57 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
||||
}
|
||||
}
|
||||
}
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if errors.IsNotFound(err) || (user != nil && user.State == int32(domain.UserStateInactive)) {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// return any error apart from not found ones directly
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if user.State == int32(domain.UserStateInactive) {
|
||||
// if there's an active user, let's use it
|
||||
if user != nil && user.State == int32(domain.UserStateActive) {
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
}
|
||||
// the user was either not found or not active
|
||||
// so check if the loginname suffix matches a verified org domain
|
||||
if repo.checkDomainDiscovery(ctx, request, loginName) {
|
||||
return nil
|
||||
}
|
||||
// let's just check for if unknown usernames are ignored
|
||||
if request.LoginPolicy != nil && request.LoginPolicy.IgnoreUnknownUsernames {
|
||||
if request.LabelPolicy != nil && request.LabelPolicy.HideLoginNameSuffix {
|
||||
preferredLoginName = loginName
|
||||
}
|
||||
request.SetUserInfo(unknownUserID, preferredLoginName, preferredLoginName, preferredLoginName, "", request.RequestedOrgID)
|
||||
return nil
|
||||
}
|
||||
// there was no policy that allowed unknown loginnames in any case
|
||||
// let's once again check if the user was just inactive
|
||||
if user != nil && user.State == int32(domain.UserStateInactive) {
|
||||
return errors.ThrowPreconditionFailed(nil, "AUTH-2n8fs", "Errors.User.Inactive")
|
||||
}
|
||||
request.SetUserInfo(user.ID, loginName, user.PreferredLoginName, "", "", user.ResourceOwner)
|
||||
return nil
|
||||
// user was not found
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkDomainDiscovery(ctx context.Context, request *domain.AuthRequest, loginName string) bool {
|
||||
// check if there's a suffix in the loginname
|
||||
split := strings.Split(loginName, "@")
|
||||
if len(split) < 2 {
|
||||
return false
|
||||
}
|
||||
// check if the suffix matches a verified domain
|
||||
org, err := repo.Query.OrgByVerifiedDomain(ctx, split[len(split)-1])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// and if the login policy allows domain discovery
|
||||
policy, err := repo.Query.LoginPolicyByID(ctx, true, org.ID)
|
||||
if err != nil || !policy.AllowDomainDiscovery {
|
||||
return false
|
||||
}
|
||||
// discovery was allowed, so set the org as requested org
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
request.Prompt = append(request.Prompt, domain.PromptCreate)
|
||||
return true
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *domain.AuthRequest, user *user_view_model.UserView) error {
|
||||
@ -1075,9 +1109,7 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = org.Domain
|
||||
request.SetOrgInformation(org.ID, org.Name, org.Domain, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1086,14 +1118,11 @@ func setOrgID(ctx context.Context, orgViewProvider orgViewProvider, request *dom
|
||||
return nil
|
||||
}
|
||||
|
||||
org, err := orgViewProvider.OrgByDomainGlobal(ctx, primaryDomain)
|
||||
org, err := orgViewProvider.OrgByPrimaryDomain(ctx, primaryDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.RequestedOrgID = org.ID
|
||||
request.RequestedOrgName = org.Name
|
||||
request.RequestedPrimaryDomain = primaryDomain
|
||||
request.RequestedOrgDomain = true
|
||||
request.SetOrgInformation(org.ID, org.Name, primaryDomain, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ func (m *mockViewOrg) OrgByID(context.Context, bool, string) (*query.Org, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mockViewOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return &query.Org{
|
||||
State: m.State,
|
||||
}, nil
|
||||
@ -186,7 +186,7 @@ func (m *mockViewErrOrg) OrgByID(context.Context, bool, string) (*query.Org, err
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
func (m *mockViewErrOrg) OrgByDomainGlobal(context.Context, string) (*query.Org, error) {
|
||||
func (m *mockViewErrOrg) OrgByPrimaryDomain(context.Context, string) (*query.Org, error) {
|
||||
return nil, errors.ThrowInternal(nil, "id", "internal error")
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ type InstanceSetup struct {
|
||||
ForceMFA bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsername bool
|
||||
AllowDomainDiscovery bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@ -217,6 +218,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
setup.LoginPolicy.ForceMFA,
|
||||
setup.LoginPolicy.HidePasswordReset,
|
||||
setup.LoginPolicy.IgnoreUnknownUsername,
|
||||
setup.LoginPolicy.AllowDomainDiscovery,
|
||||
setup.LoginPolicy.PasswordlessType,
|
||||
setup.LoginPolicy.DefaultRedirectURI,
|
||||
setup.LoginPolicy.PasswordCheckLifetime,
|
||||
|
@ -32,6 +32,7 @@ func writeModelToLoginPolicy(wm *LoginPolicyWriteModel) *domain.LoginPolicy {
|
||||
AllowExternalIDP: wm.AllowExternalIDP,
|
||||
HidePasswordReset: wm.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: wm.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: wm.AllowDomainDiscovery,
|
||||
ForceMFA: wm.ForceMFA,
|
||||
PasswordlessType: wm.PasswordlessType,
|
||||
DefaultRedirectURI: wm.DefaultRedirectURI,
|
||||
|
@ -15,37 +15,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddDefaultLoginPolicy(
|
||||
ctx context.Context,
|
||||
allowUsernamePassword, allowRegister, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime, externalLoginCheckLifetime, mfaInitSkipLifetime, secondFactorCheckLifetime, multiFactorCheckLifetime time.Duration,
|
||||
) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareAddDefaultLoginPolicy(instanceAgg, allowUsernamePassword,
|
||||
allowRegister,
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
externalLoginCheckLifetime,
|
||||
mfaInitSkipLifetime,
|
||||
secondFactorCheckLifetime,
|
||||
multiFactorCheckLifetime))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeDefaultLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
existingPolicy := NewInstanceLoginPolicyWriteModel(ctx)
|
||||
instanceAgg := InstanceAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
@ -83,6 +52,7 @@ func (c *Commands) changeDefaultLoginPolicy(ctx context.Context, instanceAgg *ev
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
@ -293,6 +263,7 @@ func prepareAddDefaultLoginPolicy(
|
||||
forceMFA bool,
|
||||
hidePasswordReset bool,
|
||||
ignoreUnknownUsernames bool,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime time.Duration,
|
||||
@ -323,6 +294,7 @@ func prepareAddDefaultLoginPolicy(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@ -66,7 +66,8 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@ -98,6 +99,9 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.IgnoreUnknownUsernames != ignoreUnknownUsernames {
|
||||
changes = append(changes, policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames))
|
||||
}
|
||||
if wm.AllowDomainDiscovery != allowDomainDiscovery {
|
||||
changes = append(changes, policy.ChangeAllowDomainDiscovery(allowDomainDiscovery))
|
||||
}
|
||||
if wm.DefaultRedirectURI != defaultRedirectURI {
|
||||
changes = append(changes, policy.ChangeDefaultRedirectURI(defaultRedirectURI))
|
||||
}
|
||||
|
@ -18,161 +18,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddDefaultLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
allowUsernamePassword bool
|
||||
allowRegister bool
|
||||
allowExternalIDP bool
|
||||
forceMFA bool
|
||||
hidePasswordReset bool
|
||||
ignoreUnknownUsernames bool
|
||||
passwordlessType domain.PasswordlessType
|
||||
defaultRedirectURI string
|
||||
passwordCheckLifetime time.Duration
|
||||
externalLoginCheckLifetime time.Duration
|
||||
mfaInitSkipLifetime time.Duration
|
||||
secondFactorCheckLifetime time.Duration
|
||||
multiFactorCheckLifetime time.Duration
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "loginpolicy already existing, already exists error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
time.Hour*1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
allowRegister: true,
|
||||
allowUsernamePassword: true,
|
||||
passwordlessType: domain.PasswordlessTypeAllowed,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add policy,ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusherWithInstanceID(
|
||||
"INSTANCE",
|
||||
instance.NewLoginPolicyAddedEvent(context.Background(),
|
||||
&instance.NewAggregate("INSTANCE").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
time.Hour*2,
|
||||
time.Hour*3,
|
||||
time.Hour*4,
|
||||
time.Hour*5,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
allowRegister: true,
|
||||
allowUsernamePassword: true,
|
||||
allowExternalIDP: true,
|
||||
forceMFA: true,
|
||||
hidePasswordReset: true,
|
||||
ignoreUnknownUsernames: true,
|
||||
passwordlessType: domain.PasswordlessTypeAllowed,
|
||||
defaultRedirectURI: "https://example.com/redirect",
|
||||
passwordCheckLifetime: time.Hour * 1,
|
||||
externalLoginCheckLifetime: time.Hour * 2,
|
||||
mfaInitSkipLifetime: time.Hour * 3,
|
||||
secondFactorCheckLifetime: time.Hour * 4,
|
||||
multiFactorCheckLifetime: time.Hour * 5,
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddDefaultLoginPolicy(
|
||||
tt.args.ctx,
|
||||
tt.args.allowUsernamePassword,
|
||||
tt.args.allowRegister,
|
||||
tt.args.allowExternalIDP,
|
||||
tt.args.forceMFA,
|
||||
tt.args.hidePasswordReset,
|
||||
tt.args.ignoreUnknownUsernames,
|
||||
tt.args.passwordlessType,
|
||||
tt.args.defaultRedirectURI,
|
||||
tt.args.passwordCheckLifetime,
|
||||
tt.args.externalLoginCheckLifetime,
|
||||
tt.args.mfaInitSkipLifetime,
|
||||
tt.args.secondFactorCheckLifetime,
|
||||
tt.args.multiFactorCheckLifetime,
|
||||
)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
@ -225,6 +70,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -246,6 +92,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -275,6 +122,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -296,6 +144,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*10,
|
||||
@ -317,6 +166,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@ -339,6 +189,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@ -435,6 +286,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -473,6 +325,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -531,6 +384,7 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -671,6 +525,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -709,6 +564,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -760,6 +616,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -816,6 +673,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -880,6 +738,7 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1434,7 +1293,7 @@ func TestCommandSide_RemoveMultiFactorDefaultLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames bool,
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime time.Duration) *instance.LoginPolicyChangedEvent {
|
||||
@ -1447,6 +1306,7 @@ func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allow
|
||||
policy.ChangeAllowUserNamePassword(allowUsernamePassword),
|
||||
policy.ChangeHidePasswordReset(hidePasswordReset),
|
||||
policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames),
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
policy.ChangePasswordCheckLifetime(passwordLifetime),
|
||||
|
@ -39,6 +39,7 @@ func (c *Commands) AddLoginPolicy(ctx context.Context, resourceOwner string, pol
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
@ -127,6 +128,7 @@ func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
|
@ -68,7 +68,8 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@ -97,6 +98,9 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.IgnoreUnknownUsernames != ignoreUnknownUsernames {
|
||||
changes = append(changes, policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames))
|
||||
}
|
||||
if wm.AllowDomainDiscovery != allowDomainDiscovery {
|
||||
changes = append(changes, policy.ChangeAllowDomainDiscovery(allowDomainDiscovery))
|
||||
}
|
||||
if wm.PasswordCheckLifetime != passwordCheckLifetime {
|
||||
changes = append(changes, policy.ChangePasswordCheckLifetime(passwordCheckLifetime))
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -100,6 +101,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -130,6 +132,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -153,6 +156,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -174,6 +178,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -202,6 +207,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -233,6 +239,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -268,6 +275,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -291,6 +299,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -320,6 +329,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -368,6 +378,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -398,6 +409,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -425,6 +437,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -489,6 +502,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
@ -514,6 +528,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
@ -537,6 +552,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -559,6 +575,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@ -587,6 +604,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@ -608,6 +626,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
&duration10,
|
||||
@ -630,6 +649,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
AllowExternalIDP: false,
|
||||
ForceMFA: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@ -651,6 +671,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@ -744,6 +765,7 @@ func TestCommandSide_RemoveLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -884,6 +906,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -925,6 +948,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -986,6 +1010,7 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1150,6 +1175,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1191,6 +1217,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1244,6 +1271,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1304,6 +1332,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1372,6 +1401,7 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1990,7 +2020,7 @@ func TestCommandSide_RemoveMultiFactorLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames bool,
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime *time.Duration) *org.LoginPolicyChangedEvent {
|
||||
@ -2001,6 +2031,7 @@ func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassw
|
||||
policy.ChangeForceMFA(mfa),
|
||||
policy.ChangeHidePasswordReset(passwordReset),
|
||||
policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames),
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ type LoginPolicyWriteModel struct {
|
||||
ForceMFA bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@ -38,6 +39,7 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
wm.PasswordlessType = e.PasswordlessType
|
||||
wm.HidePasswordReset = e.HidePasswordReset
|
||||
wm.IgnoreUnknownUsernames = e.IgnoreUnknownUsernames
|
||||
wm.AllowDomainDiscovery = e.AllowDomainDiscovery
|
||||
wm.DefaultRedirectURI = e.DefaultRedirectURI
|
||||
wm.PasswordCheckLifetime = e.PasswordCheckLifetime
|
||||
wm.ExternalLoginCheckLifetime = e.ExternalLoginCheckLifetime
|
||||
@ -64,6 +66,9 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
if e.IgnoreUnknownUsernames != nil {
|
||||
wm.IgnoreUnknownUsernames = *e.IgnoreUnknownUsernames
|
||||
}
|
||||
if e.AllowDomainDiscovery != nil {
|
||||
wm.AllowDomainDiscovery = *e.AllowDomainDiscovery
|
||||
}
|
||||
if e.PasswordlessType != nil {
|
||||
wm.PasswordlessType = *e.PasswordlessType
|
||||
}
|
||||
|
@ -1157,6 +1157,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1194,6 +1195,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1232,6 +1234,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1286,6 +1289,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1374,6 +1378,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1469,6 +1474,7 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@ -1679,6 +1679,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1745,6 +1746,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1811,6 +1813,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -1894,6 +1897,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -2035,6 +2039,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -2144,6 +2149,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -2247,6 +2253,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@ -2372,6 +2379,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@ -140,6 +140,13 @@ func (a *AuthRequest) SetUserInfo(userID, userName, loginName, displayName, avat
|
||||
a.UserOrgID = userOrgID
|
||||
}
|
||||
|
||||
func (a *AuthRequest) SetOrgInformation(id, name, primaryDomain string, requestedByDomain bool) {
|
||||
a.RequestedOrgID = id
|
||||
a.RequestedOrgName = name
|
||||
a.RequestedPrimaryDomain = primaryDomain
|
||||
a.RequestedOrgDomain = requestedByDomain
|
||||
}
|
||||
|
||||
func (a *AuthRequest) MFALevel() MFALevel {
|
||||
return -1
|
||||
//PLANNED: check a.PossibleLOAs (and Prompt Login?)
|
||||
|
@ -21,6 +21,7 @@ type LoginPolicy struct {
|
||||
PasswordlessType PasswordlessType
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
|
@ -30,6 +30,7 @@ type LoginPolicy struct {
|
||||
IsDefault bool
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
@ -113,6 +114,10 @@ var (
|
||||
name: projection.IgnoreUnknownUsernames,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnAllowDomainDiscovery = Column{
|
||||
name: projection.AllowDomainDiscovery,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnDefaultRedirectURI = Column{
|
||||
name: projection.DefaultRedirectURI,
|
||||
table: loginPolicyTable,
|
||||
@ -305,6 +310,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
LoginPolicyColumnIsDefault.identifier(),
|
||||
LoginPolicyColumnHidePasswordReset.identifier(),
|
||||
LoginPolicyColumnIgnoreUnknownUsernames.identifier(),
|
||||
LoginPolicyColumnAllowDomainDiscovery.identifier(),
|
||||
LoginPolicyColumnDefaultRedirectURI.identifier(),
|
||||
LoginPolicyColumnPasswordCheckLifetime.identifier(),
|
||||
LoginPolicyColumnExternalLoginCheckLifetime.identifier(),
|
||||
@ -343,6 +349,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
&p.IsDefault,
|
||||
&p.HidePasswordReset,
|
||||
&p.IgnoreUnknownUsernames,
|
||||
&p.AllowDomainDiscovery,
|
||||
&defaultRedirectURI,
|
||||
&p.PasswordCheckLifetime,
|
||||
&p.ExternalLoginCheckLifetime,
|
||||
|
@ -30,32 +30,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
nil,
|
||||
@ -75,32 +76,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
[]string{
|
||||
@ -118,6 +120,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
"is_default",
|
||||
"hide_password_reset",
|
||||
"ignore_unknown_usernames",
|
||||
"allow_domain_discovery",
|
||||
"default_redirect_uri",
|
||||
"password_check_lifetime",
|
||||
"external_login_check_lifetime",
|
||||
@ -143,6 +146,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Hour * 2,
|
||||
time.Hour * 2,
|
||||
@ -170,6 +174,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
IsDefault: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 2,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
@ -190,32 +195,33 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.aggregate_id,`+
|
||||
` projections.login_policies.creation_date,`+
|
||||
` projections.login_policies.change_date,`+
|
||||
` projections.login_policies.sequence,`+
|
||||
` projections.login_policies.allow_register,`+
|
||||
` projections.login_policies.allow_username_password,`+
|
||||
` projections.login_policies.allow_external_idps,`+
|
||||
` projections.login_policies.force_mfa,`+
|
||||
` projections.login_policies.second_factors,`+
|
||||
` projections.login_policies.multi_factors,`+
|
||||
` projections.login_policies.passwordless_type,`+
|
||||
` projections.login_policies.is_default,`+
|
||||
` projections.login_policies.hide_password_reset,`+
|
||||
` projections.login_policies.ignore_unknown_usernames,`+
|
||||
` projections.login_policies.default_redirect_uri,`+
|
||||
` projections.login_policies.password_check_lifetime,`+
|
||||
` projections.login_policies.external_login_check_lifetime,`+
|
||||
` projections.login_policies.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies.second_factor_check_lifetime,`+
|
||||
` projections.login_policies.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies`+
|
||||
` FROM projections.login_policies2`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
sql.ErrConnDone,
|
||||
@ -234,8 +240,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@ -255,8 +261,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@ -277,8 +283,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@ -294,8 +300,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.second_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
@ -312,8 +318,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@ -333,8 +339,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@ -355,8 +361,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@ -372,8 +378,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies.multi_factors`+
|
||||
` FROM projections.login_policies`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
|
@ -104,7 +104,7 @@ func (q *Queries) OrgByID(ctx context.Context, shouldTriggerBulk bool, id string
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) OrgByDomainGlobal(ctx context.Context, domain string) (*Org, error) {
|
||||
func (q *Queries) OrgByPrimaryDomain(ctx context.Context, domain string) (*Org, error) {
|
||||
stmt, scan := prepareOrgQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OrgColumnDomain.identifier(): domain,
|
||||
@ -118,6 +118,21 @@ func (q *Queries) OrgByDomainGlobal(ctx context.Context, domain string) (*Org, e
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) OrgByVerifiedDomain(ctx context.Context, domain string) (*Org, error) {
|
||||
stmt, scan := prepareOrgWithDomainsQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OrgDomainDomainCol.identifier(): domain,
|
||||
OrgDomainIsVerifiedCol.identifier(): true,
|
||||
OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-TYUCE", "Errors.Query.SQLStatement")
|
||||
}
|
||||
|
||||
row := q.client.QueryRowContext(ctx, query, args...)
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) IsOrgUnique(ctx context.Context, name, domain string) (isUnique bool, err error) {
|
||||
if name == "" && domain == "" {
|
||||
return false, errors.ThrowInvalidArgument(nil, "QUERY-DGqfd", "Errors.Query.InvalidRequest")
|
||||
@ -268,6 +283,42 @@ func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
|
||||
}
|
||||
}
|
||||
|
||||
func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
|
||||
return sq.Select(
|
||||
OrgColumnID.identifier(),
|
||||
OrgColumnCreationDate.identifier(),
|
||||
OrgColumnChangeDate.identifier(),
|
||||
OrgColumnResourceOwner.identifier(),
|
||||
OrgColumnState.identifier(),
|
||||
OrgColumnSequence.identifier(),
|
||||
OrgColumnName.identifier(),
|
||||
OrgColumnDomain.identifier(),
|
||||
).
|
||||
From(orgsTable.identifier()).
|
||||
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*Org, error) {
|
||||
o := new(Org)
|
||||
err := row.Scan(
|
||||
&o.ID,
|
||||
&o.CreationDate,
|
||||
&o.ChangeDate,
|
||||
&o.ResourceOwner,
|
||||
&o.State,
|
||||
&o.Sequence,
|
||||
&o.Name,
|
||||
&o.Domain,
|
||||
)
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound")
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal")
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareOrgUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
|
||||
return sq.Select(uniqueColumn.identifier()).
|
||||
From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
LoginPolicyTable = "projections.login_policies"
|
||||
LoginPolicyTable = "projections.login_policies2"
|
||||
|
||||
LoginPolicyIDCol = "aggregate_id"
|
||||
LoginPolicyInstanceIDCol = "instance_id"
|
||||
@ -30,6 +30,7 @@ const (
|
||||
LoginPolicyPasswordlessTypeCol = "passwordless_type"
|
||||
LoginPolicyHidePWResetCol = "hide_password_reset"
|
||||
IgnoreUnknownUsernames = "ignore_unknown_usernames"
|
||||
AllowDomainDiscovery = "allow_domain_discovery"
|
||||
DefaultRedirectURI = "default_redirect_uri"
|
||||
PasswordCheckLifetimeCol = "password_check_lifetime"
|
||||
ExternalLoginCheckLifetimeCol = "external_login_check_lifetime"
|
||||
@ -63,6 +64,7 @@ func newLoginPolicyProjection(ctx context.Context, config crdb.StatementHandlerC
|
||||
crdb.NewColumn(LoginPolicyPasswordlessTypeCol, crdb.ColumnTypeEnum),
|
||||
crdb.NewColumn(LoginPolicyHidePWResetCol, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(IgnoreUnknownUsernames, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(AllowDomainDiscovery, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(DefaultRedirectURI, crdb.ColumnTypeText, crdb.Nullable()),
|
||||
crdb.NewColumn(PasswordCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
crdb.NewColumn(ExternalLoginCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
@ -172,6 +174,7 @@ func (p *loginPolicyProjection) reduceLoginPolicyAdded(event eventstore.Event) (
|
||||
handler.NewCol(LoginPolicyIsDefaultCol, isDefault),
|
||||
handler.NewCol(LoginPolicyHidePWResetCol, policyEvent.HidePasswordReset),
|
||||
handler.NewCol(IgnoreUnknownUsernames, policyEvent.IgnoreUnknownUsernames),
|
||||
handler.NewCol(AllowDomainDiscovery, policyEvent.AllowDomainDiscovery),
|
||||
handler.NewCol(DefaultRedirectURI, policyEvent.DefaultRedirectURI),
|
||||
handler.NewCol(PasswordCheckLifetimeCol, policyEvent.PasswordCheckLifetime),
|
||||
handler.NewCol(ExternalLoginCheckLifetimeCol, policyEvent.ExternalLoginCheckLifetime),
|
||||
@ -217,6 +220,9 @@ func (p *loginPolicyProjection) reduceLoginPolicyChanged(event eventstore.Event)
|
||||
if policyEvent.IgnoreUnknownUsernames != nil {
|
||||
cols = append(cols, handler.NewCol(IgnoreUnknownUsernames, *policyEvent.IgnoreUnknownUsernames))
|
||||
}
|
||||
if policyEvent.AllowDomainDiscovery != nil {
|
||||
cols = append(cols, handler.NewCol(AllowDomainDiscovery, *policyEvent.AllowDomainDiscovery))
|
||||
}
|
||||
if policyEvent.DefaultRedirectURI != nil {
|
||||
cols = append(cols, handler.NewCol(DefaultRedirectURI, *policyEvent.DefaultRedirectURI))
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
want wantReduce
|
||||
}{
|
||||
{
|
||||
name: "org.reduceLoginPolicyAdded",
|
||||
name: "org reduceLoginPolicyAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(org.LoginPolicyAddedEventType),
|
||||
@ -36,6 +36,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": false,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@ -55,7 +56,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@ -70,6 +71,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@ -83,7 +85,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceLoginPolicyChanged",
|
||||
name: "org reduceLoginPolicyChanged",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyChanged,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -96,6 +98,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": true,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@ -114,7 +117,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) WHERE (aggregate_id = $16)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) WHERE (aggregate_id = $17)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -125,6 +128,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
domain.PasswordlessTypeAllowed,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@ -139,7 +143,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceMFAAdded",
|
||||
name: "org reduceMFAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -158,7 +162,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -171,7 +175,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceMFARemoved",
|
||||
name: "org reduceMFARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -190,7 +194,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -203,7 +207,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduceLoginPolicyRemoved",
|
||||
name: "org reduceLoginPolicyRemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyRemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -220,7 +224,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.login_policies WHERE (aggregate_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.login_policies2 WHERE (aggregate_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
@ -230,7 +234,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduce2FAAdded",
|
||||
name: "org reduce2FAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -249,7 +253,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -262,7 +266,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "org.reduce2FARemoved",
|
||||
name: "org reduce2FARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -281,7 +285,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -294,7 +298,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceLoginPolicyAdded",
|
||||
name: "instance reduceLoginPolicyAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -307,6 +311,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": false,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@ -325,7 +330,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@ -340,6 +345,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@ -353,7 +359,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceLoginPolicyChanged",
|
||||
name: "instance reduceLoginPolicyChanged",
|
||||
reduce: (&loginPolicyProjection{}).reduceLoginPolicyChanged,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -366,6 +372,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"forceMFA": true,
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect"
|
||||
}`),
|
||||
@ -379,7 +386,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) WHERE (aggregate_id = $11)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) WHERE (aggregate_id = $12)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -390,6 +397,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
domain.PasswordlessTypeAllowed,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
"agg-id",
|
||||
},
|
||||
@ -399,7 +407,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceMFAAdded",
|
||||
name: "instance reduceMFAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -418,7 +426,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -431,7 +439,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduceMFARemoved",
|
||||
name: "instance reduceMFARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduceMFARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -450,7 +458,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -463,7 +471,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduce2FAAdded",
|
||||
name: "instance reduce2FAAdded",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FAAdded,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -482,7 +490,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@ -495,7 +503,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance.reduce2FARemoved",
|
||||
name: "instance reduce2FARemoved",
|
||||
reduce: (&loginPolicyProjection{}).reduce2FARemoved,
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
@ -514,7 +522,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@ -28,7 +28,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@ -49,6 +50,7 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@ -29,7 +29,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@ -50,6 +51,7 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@ -26,6 +26,7 @@ type LoginPolicyAddedEvent struct {
|
||||
ForceMFA bool `json:"forceMFA,omitempty"`
|
||||
HidePasswordReset bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery bool `json:"allowDomainDiscovery,omitempty"`
|
||||
PasswordlessType domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@ -50,7 +51,8 @@ func NewLoginPolicyAddedEvent(
|
||||
allowExternalIDP,
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames bool,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@ -68,6 +70,7 @@ func NewLoginPolicyAddedEvent(
|
||||
PasswordlessType: passwordlessType,
|
||||
HidePasswordReset: hidePasswordReset,
|
||||
IgnoreUnknownUsernames: ignoreUnknownUsernames,
|
||||
AllowDomainDiscovery: allowDomainDiscovery,
|
||||
DefaultRedirectURI: defaultRedirectURI,
|
||||
PasswordCheckLifetime: passwordCheckLifetime,
|
||||
ExternalLoginCheckLifetime: externalLoginCheckLifetime,
|
||||
@ -99,6 +102,7 @@ type LoginPolicyChangedEvent struct {
|
||||
ForceMFA *bool `json:"forceMFA,omitempty"`
|
||||
HidePasswordReset *bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames *bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery *bool `json:"allowDomainDiscovery,omitempty"`
|
||||
PasswordlessType *domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI *string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime *time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@ -206,6 +210,12 @@ func ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames bool) func(*LoginPolicy
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeAllowDomainDiscovery(allowDomainDiscovery bool) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.AllowDomainDiscovery = &allowDomainDiscovery
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeDefaultRedirectURI(defaultRedirectURI string) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.DefaultRedirectURI = &defaultRedirectURI
|
||||
|
@ -3798,7 +3798,7 @@ message UpdateLabelPolicyRequest {
|
||||
];
|
||||
bool hide_login_name_suffix = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes";
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set";
|
||||
}
|
||||
];
|
||||
string warn_color = 4 [(validate.rules).string = {max_len: 50}];
|
||||
@ -3910,6 +3910,12 @@ message UpdateLoginPolicyRequest {
|
||||
google.protobuf.Duration mfa_init_skip_lifetime = 11;
|
||||
google.protobuf.Duration second_factor_check_lifetime = 12;
|
||||
google.protobuf.Duration multi_factor_check_lifetime = 13;
|
||||
// If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success.
|
||||
bool allow_domain_discovery = 14 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message UpdateLoginPolicyResponse {
|
||||
@ -4852,4 +4858,4 @@ message ExportDataRequest {
|
||||
|
||||
message ExportDataResponse {
|
||||
repeated DataOrg orgs = 1;
|
||||
}
|
||||
}
|
||||
|
@ -4585,6 +4585,12 @@ message AddCustomLoginPolicyRequest {
|
||||
repeated zitadel.policy.v1.SecondFactorType second_factors = 14;
|
||||
repeated zitadel.policy.v1.MultiFactorType multi_factors = 15;
|
||||
repeated IDP idps = 16;
|
||||
// If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success.
|
||||
bool allow_domain_discovery = 17 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message AddCustomLoginPolicyResponse {
|
||||
@ -4613,6 +4619,12 @@ message UpdateCustomLoginPolicyRequest {
|
||||
google.protobuf.Duration mfa_init_skip_lifetime = 11;
|
||||
google.protobuf.Duration second_factor_check_lifetime = 12;
|
||||
google.protobuf.Duration multi_factor_check_lifetime = 13;
|
||||
// If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success.
|
||||
bool allow_domain_discovery = 14 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
message UpdateCustomLoginPolicyResponse {
|
||||
@ -4890,10 +4902,10 @@ message GetDefaultLabelPolicyResponse {
|
||||
|
||||
message AddCustomLabelPolicyRequest {
|
||||
string primary_color = 1 [(validate.rules).string = {max_len: 50}];
|
||||
// hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes
|
||||
// hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set
|
||||
bool hide_login_name_suffix = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes";
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set";
|
||||
}
|
||||
];
|
||||
string warn_color = 4 [(validate.rules).string = {max_len: 50}];
|
||||
@ -4914,7 +4926,7 @@ message UpdateCustomLabelPolicyRequest {
|
||||
string primary_color = 1 [(validate.rules).string = {max_len: 50}];
|
||||
bool hide_login_name_suffix = 3 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes";
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set";
|
||||
}
|
||||
];
|
||||
string warn_color = 4 [(validate.rules).string = {max_len: 50}];
|
||||
|
@ -62,10 +62,10 @@ message LabelPolicy {
|
||||
description: "defines if the organisation's admin changed the policy"
|
||||
}
|
||||
];
|
||||
// hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes
|
||||
// hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set
|
||||
bool hide_login_name_suffix = 5 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set. Details about this scope in https://docs.zitadel.com/concepts#Reserved_Scopes";
|
||||
description: "hides the org suffix on the login form if the scope \"urn:zitadel:iam:org:domain:primary:{domainname}\" is set";
|
||||
}
|
||||
];
|
||||
// hex value for secondary color
|
||||
@ -173,6 +173,12 @@ message LoginPolicy {
|
||||
repeated SecondFactorType second_factors = 16;
|
||||
repeated MultiFactorType multi_factors = 17;
|
||||
repeated zitadel.idp.v1.IDPLoginPolicyLink idps = 18;
|
||||
// If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success.
|
||||
bool allow_domain_discovery = 19 [
|
||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
description: "If set to true, the suffix (@domain.com) of an unknown username input on the login screen will be matched against the org domains and will redirect to the registration of that organisation on success."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
enum SecondFactorType {
|
||||
|
Loading…
x
Reference in New Issue
Block a user