mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-04 23:45:07 +00:00
fix(console): keep default idps active (#7663)
* fix(console): keep default idps active * rename var * rename var * use Promise.all() * lint --------- Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
parent
d229da6af7
commit
2de66dcf95
@ -36,7 +36,7 @@ import { ContextChangedWorkflowOverlays } from 'src/app/services/overlay/workflo
|
||||
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
import { ActivateIdpService } from '../../services/activate-idp.service';
|
||||
import { LoginPolicyService } from '../../services/login-policy.service';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
@ -72,7 +72,7 @@ export class IdpTableComponent implements OnInit, OnDestroy {
|
||||
private toast: ToastService,
|
||||
private dialog: MatDialog,
|
||||
private router: Router,
|
||||
private activateIdpSvc: ActivateIdpService,
|
||||
private loginPolicySvc: LoginPolicyService,
|
||||
) {
|
||||
this.selection.changed.subscribe(() => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
@ -302,7 +302,7 @@ export class IdpTableComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public addIdp(idp: Provider.AsObject): Promise<any> {
|
||||
return firstValueFrom(this.activateIdpSvc.activateIdp(this.service, idp.id, idp.owner, this.loginPolicy))
|
||||
return firstValueFrom(this.loginPolicySvc.activateIdp(this.service, idp.id, idp.owner, this.loginPolicy))
|
||||
.then(() => {
|
||||
this.toast.showInfo('IDP.TOAST.ADDED', true);
|
||||
setTimeout(() => {
|
||||
@ -328,8 +328,8 @@ export class IdpTableComponent implements OnInit, OnDestroy {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
if (this.isDefault) {
|
||||
this.activateIdpSvc
|
||||
.addLoginPolicy(this.service as ManagementService, this.loginPolicy)
|
||||
this.loginPolicySvc
|
||||
.createCustomLoginPolicy(this.service as ManagementService, this.loginPolicy)
|
||||
.then(() => {
|
||||
this.loginPolicy.isDefault = false;
|
||||
return (this.service as ManagementService)
|
||||
|
@ -26,6 +26,7 @@ import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { LoginMethodComponentType } from './factor-table/factor-table.component';
|
||||
import { catchError, map, takeUntil } from 'rxjs/operators';
|
||||
import { error } from 'console';
|
||||
import { LoginPolicyService } from '../../../services/login-policy.service';
|
||||
|
||||
const minValueValidator = (minValue: number) => (control: AbstractControl) => {
|
||||
const value = control.value;
|
||||
@ -71,6 +72,7 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
private fb: UntypedFormBuilder,
|
||||
private authService: GrpcAuthService,
|
||||
private dialog: MatDialog,
|
||||
private loginPolicySvc: LoginPolicyService,
|
||||
) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@ -172,45 +174,13 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private async updateData(): Promise<any> {
|
||||
const calls: Observable<any>[] = [];
|
||||
const calls: Promise<any>[] = [];
|
||||
|
||||
if (this.loginData) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
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.setForceMfaLocalOnly(this.loginData.forceMfaLocalOnly);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(this.loginData.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(this.loginData.secondFactorsList);
|
||||
mgmtreq.setDisableLoginWithEmail(this.loginData.disableLoginWithEmail);
|
||||
mgmtreq.setDisableLoginWithPhone(this.loginData.disableLoginWithPhone);
|
||||
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 0) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 0) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 0) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 0) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 0) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(this.loginData.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
calls.push(from((this.service as ManagementService).addCustomLoginPolicy(mgmtreq)));
|
||||
calls.push(this.loginPolicySvc.createCustomLoginPolicy(this.service as ManagementService, this.loginData));
|
||||
break;
|
||||
} else {
|
||||
const mgmtreq = new UpdateCustomLoginPolicyRequest();
|
||||
@ -243,7 +213,7 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
calls.push(from((this.service as ManagementService).updateCustomLoginPolicy(mgmtreq)));
|
||||
calls.push((this.service as ManagementService).updateCustomLoginPolicy(mgmtreq));
|
||||
break;
|
||||
}
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
@ -276,21 +246,19 @@ export class LoginPolicyComponent implements OnInit, OnDestroy {
|
||||
adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
adminreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
calls.push(from((this.service as AdminService).setRestrictions(!this.allowOrgRegistration)));
|
||||
calls.push(from((this.service as AdminService).updateLoginPolicy(adminreq)));
|
||||
calls.push((this.service as AdminService).setRestrictions(!this.allowOrgRegistration));
|
||||
calls.push((this.service as AdminService).updateLoginPolicy(adminreq));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
calls.push(from(Promise.reject()));
|
||||
calls.push(Promise.reject());
|
||||
}
|
||||
return firstValueFrom(
|
||||
forkJoin(calls).pipe(
|
||||
catchError((error, caught) => {
|
||||
// We just ignore the policy not changed error!
|
||||
return (error as { message: string }).message.includes('INSTANCE-5M9vdd') ? of(true) : caught;
|
||||
}),
|
||||
),
|
||||
);
|
||||
return Promise.all(calls).catch((err) => {
|
||||
if (err?.message?.includes('INSTANCE-5M9vdd')) {
|
||||
return true;
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
|
@ -8,7 +8,7 @@ import { AdminService } from '../../../services/admin.service';
|
||||
import { IDPOwnerType } from '../../../proto/generated/zitadel/idp_pb';
|
||||
import { ToastService } from '../../../services/toast.service';
|
||||
import { Data, ParamMap } from '@angular/router';
|
||||
import { ActivateIdpService } from '../../../services/activate-idp.service';
|
||||
import { LoginPolicyService } from '../../../services/login-policy.service';
|
||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||
|
||||
@Injectable({
|
||||
@ -18,7 +18,7 @@ export class ProviderNextService {
|
||||
constructor(
|
||||
private env: EnvironmentService,
|
||||
private toast: ToastService,
|
||||
private addIdpSvc: ActivateIdpService,
|
||||
private loginPolicySvc: LoginPolicyService,
|
||||
private injector: Injector,
|
||||
) {}
|
||||
|
||||
@ -117,7 +117,7 @@ export class ProviderNextService {
|
||||
if (!id) {
|
||||
throw new Error('No ID');
|
||||
}
|
||||
return this.addIdpSvc.activateIdp(
|
||||
return this.loginPolicySvc.activateIdp(
|
||||
service,
|
||||
id,
|
||||
service instanceof AdminService ? IDPOwnerType.IDP_OWNER_TYPE_SYSTEM : IDPOwnerType.IDP_OWNER_TYPE_ORG,
|
||||
|
@ -1,103 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, combineLatest, from, map, Observable, of, switchMap } from 'rxjs';
|
||||
|
||||
import { ManagementService } from './mgmt.service';
|
||||
import { AddCustomLoginPolicyRequest, AddCustomLoginPolicyResponse } from '../proto/generated/zitadel/management_pb';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { IDPOwnerType, Provider } from '../proto/generated/zitadel/idp_pb';
|
||||
import { AdminService } from './admin.service';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { LoginPolicy } from '../proto/generated/zitadel/policy_pb';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ActivateIdpService {
|
||||
constructor() {}
|
||||
|
||||
public activateIdp(
|
||||
service: AdminService | ManagementService,
|
||||
id: string,
|
||||
owner?: IDPOwnerType,
|
||||
policy?: LoginPolicy.AsObject,
|
||||
): Observable<any> {
|
||||
const isAdmin = service instanceof AdminService;
|
||||
if (isAdmin) {
|
||||
service.addIDPToLoginPolicy(id);
|
||||
}
|
||||
|
||||
if (!isAdmin && owner !== IDPOwnerType.IDP_OWNER_TYPE_SYSTEM && owner !== IDPOwnerType.IDP_OWNER_TYPE_ORG) {
|
||||
throw new Error('Must specify owner for management service');
|
||||
}
|
||||
|
||||
return from(service.addIDPToLoginPolicy(id!, owner!)).pipe(
|
||||
catchError((error) => {
|
||||
if (isAdmin || error.code != 5) {
|
||||
throw error;
|
||||
}
|
||||
// No org policy was found, so we create a new one
|
||||
return from(policy ? of(policy) : from(service.getLoginPolicy()).pipe(map((policy) => policy.policy))).pipe(
|
||||
switchMap((policy) => {
|
||||
if (!policy?.isDefault) {
|
||||
// There is already an org policy
|
||||
throw error;
|
||||
}
|
||||
return from(this.addLoginPolicy(service, policy)).pipe(
|
||||
switchMap(() => from(service.addIDPToLoginPolicy(id!, owner!))),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public addLoginPolicy(
|
||||
service: ManagementService,
|
||||
policy: LoginPolicy.AsObject,
|
||||
): Promise<AddCustomLoginPolicyResponse.AsObject> {
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(policy.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(policy.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(policy.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(policy.forceMfa);
|
||||
mgmtreq.setPasswordlessType(policy.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(policy.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(policy.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(policy.secondFactorsList);
|
||||
|
||||
const pcl = new Duration()
|
||||
.setSeconds(policy.passwordCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(policy.passwordCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration()
|
||||
.setSeconds(policy.externalLoginCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(policy.externalLoginCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration()
|
||||
.setSeconds(policy.mfaInitSkipLifetime?.seconds ?? 0)
|
||||
.setNanos(policy.mfaInitSkipLifetime?.nanos ?? 0);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration()
|
||||
.setSeconds(policy.secondFactorCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(policy.secondFactorCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration()
|
||||
.setSeconds(policy.multiFactorCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(policy.multiFactorCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(policy.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(policy.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(policy.defaultRedirectUri);
|
||||
|
||||
mgmtreq.setDisableLoginWithEmail(policy.disableLoginWithEmail);
|
||||
mgmtreq.setDisableLoginWithPhone(policy.disableLoginWithPhone);
|
||||
mgmtreq.setForceMfaLocalOnly(policy.forceMfaLocalOnly);
|
||||
|
||||
return service.addCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
}
|
115
console/src/app/services/login-policy.service.ts
Normal file
115
console/src/app/services/login-policy.service.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { from, map, Observable, of, switchMap } from 'rxjs';
|
||||
|
||||
import { ManagementService } from './mgmt.service';
|
||||
import { AddCustomLoginPolicyRequest, AddCustomLoginPolicyResponse } from '../proto/generated/zitadel/management_pb';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { IDPOwnerType } from '../proto/generated/zitadel/idp_pb';
|
||||
import { AdminService } from './admin.service';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { LoginPolicy } from '../proto/generated/zitadel/policy_pb';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LoginPolicyService {
|
||||
constructor() {}
|
||||
|
||||
public activateIdp(
|
||||
service: AdminService | ManagementService,
|
||||
id: string,
|
||||
owner?: IDPOwnerType,
|
||||
policy?: LoginPolicy.AsObject,
|
||||
): Observable<any> {
|
||||
const isAdmin = service instanceof AdminService;
|
||||
if (isAdmin) {
|
||||
service.addIDPToLoginPolicy(id);
|
||||
}
|
||||
|
||||
if (!isAdmin && owner !== IDPOwnerType.IDP_OWNER_TYPE_SYSTEM && owner !== IDPOwnerType.IDP_OWNER_TYPE_ORG) {
|
||||
throw new Error('Must specify owner for management service');
|
||||
}
|
||||
|
||||
return from(service.addIDPToLoginPolicy(id!, owner!)).pipe(
|
||||
catchError((error) => {
|
||||
if (isAdmin || error.code != 5) {
|
||||
throw error;
|
||||
}
|
||||
// No org policy was found, so we create a new one
|
||||
return from(policy ? of(policy) : from(service.getLoginPolicy()).pipe(map((policy) => policy.policy))).pipe(
|
||||
switchMap((policy) => {
|
||||
if (!policy?.isDefault) {
|
||||
// There is already an org policy
|
||||
throw error;
|
||||
}
|
||||
return from(this.createCustomLoginPolicy(service, policy, id));
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public createCustomLoginPolicy(
|
||||
service: ManagementService,
|
||||
fromDefaultPolicy: LoginPolicy.AsObject,
|
||||
activateOrgIdp?: string,
|
||||
): Promise<AddCustomLoginPolicyResponse.AsObject> {
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(fromDefaultPolicy.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(fromDefaultPolicy.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(fromDefaultPolicy.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(fromDefaultPolicy.forceMfa);
|
||||
mgmtreq.setPasswordlessType(fromDefaultPolicy.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(fromDefaultPolicy.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(fromDefaultPolicy.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(fromDefaultPolicy.secondFactorsList);
|
||||
|
||||
const pcl = new Duration()
|
||||
.setSeconds(fromDefaultPolicy.passwordCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(fromDefaultPolicy.passwordCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration()
|
||||
.setSeconds(fromDefaultPolicy.externalLoginCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(fromDefaultPolicy.externalLoginCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration()
|
||||
.setSeconds(fromDefaultPolicy.mfaInitSkipLifetime?.seconds ?? 0)
|
||||
.setNanos(fromDefaultPolicy.mfaInitSkipLifetime?.nanos ?? 0);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration()
|
||||
.setSeconds(fromDefaultPolicy.secondFactorCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(fromDefaultPolicy.secondFactorCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration()
|
||||
.setSeconds(fromDefaultPolicy.multiFactorCheckLifetime?.seconds ?? 0)
|
||||
.setNanos(fromDefaultPolicy.multiFactorCheckLifetime?.nanos ?? 0);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setAllowDomainDiscovery(fromDefaultPolicy.allowDomainDiscovery);
|
||||
mgmtreq.setIgnoreUnknownUsernames(fromDefaultPolicy.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(fromDefaultPolicy.defaultRedirectUri);
|
||||
|
||||
mgmtreq.setDisableLoginWithEmail(fromDefaultPolicy.disableLoginWithEmail);
|
||||
mgmtreq.setDisableLoginWithPhone(fromDefaultPolicy.disableLoginWithPhone);
|
||||
mgmtreq.setForceMfaLocalOnly(fromDefaultPolicy.forceMfaLocalOnly);
|
||||
|
||||
mgmtreq.setIdpsList(
|
||||
fromDefaultPolicy.idpsList.map((idp) => addIdpMessage(idp.idpId, IDPOwnerType.IDP_OWNER_TYPE_SYSTEM)),
|
||||
);
|
||||
if (activateOrgIdp) {
|
||||
mgmtreq.addIdps(addIdpMessage(activateOrgIdp, IDPOwnerType.IDP_OWNER_TYPE_ORG));
|
||||
}
|
||||
return service.addCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
}
|
||||
|
||||
function addIdpMessage(id: string, owner: IDPOwnerType): AddCustomLoginPolicyRequest.IDP {
|
||||
const addIdp = new AddCustomLoginPolicyRequest.IDP();
|
||||
addIdp.setIdpId(id);
|
||||
addIdp.setOwnertype(owner);
|
||||
return addIdp;
|
||||
}
|
Loading…
Reference in New Issue
Block a user