diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml
index 6841d8c8b..6539457b2 100644
--- a/cmd/defaults.yaml
+++ b/cmd/defaults.yaml
@@ -307,6 +307,13 @@ SystemDefaults:
PublicKeyLifetime: 30h
CertificateLifetime: 8766h
+Actions:
+ HTTP:
+ # wildcard sub domains are currently unsupported
+ DenyList:
+ - localhost
+ - '127.0.0.1'
+
DefaultInstance:
InstanceName:
DefaultLanguage: en
diff --git a/cmd/start/config.go b/cmd/start/config.go
index a3d8e9c86..078e3ce1d 100644
--- a/cmd/start/config.go
+++ b/cmd/start/config.go
@@ -8,6 +8,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/saml"
+ "github.com/zitadel/zitadel/internal/actions"
admin_es "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing"
internal_authz "github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/http/middleware"
@@ -58,6 +59,7 @@ type Config struct {
SystemAPIUsers map[string]*internal_authz.SystemAPIUser
CustomerPortal string
Machine *id.Config
+ Actions *actions.Config
}
func MustNewConfig(v *viper.Viper) *Config {
@@ -70,6 +72,7 @@ func MustNewConfig(v *viper.Viper) *Config {
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToSliceHookFunc(","),
database.DecodeHook,
+ actions.HTTPConfigDecodeHook,
)),
)
logging.OnError(err).Fatal("unable to read config")
@@ -84,6 +87,7 @@ func MustNewConfig(v *viper.Viper) *Config {
logging.OnError(err).Fatal("unable to set meter")
id.Configure(config.Machine)
+ actions.SetHTTPConfig(&config.Actions.HTTP)
return config
}
diff --git a/console/src/app/pages/actions/actions.component.html b/console/src/app/pages/actions/actions.component.html
index df9d75796..c0c60c7ab 100644
--- a/console/src/app/pages/actions/actions.component.html
+++ b/console/src/app/pages/actions/actions.component.html
@@ -21,12 +21,12 @@
{{ 'FLOWS.FLOWSDESCRIPTION' | translate }}
-
+
{{ 'FLOWS.FLOWTYPE' | translate }}
- {{ 'FLOWS.TYPES.' + type | translate }}
+ {{ type.name?.localizedMessage }}
@@ -36,8 +36,14 @@
- {{ 'FLOWS.TYPES.' + flow.type | translate }}
-
@@ -45,7 +51,11 @@
- {{ 'FLOWS.TRIGGERTYPES.' + trigger.triggerType | translate }}
+ {{ trigger.triggerType?.name?.localizedMessage }}
+
+
+
+
@@ -72,7 +82,13 @@
-
+
add
{{ 'FLOWS.ADDTRIGGER' | translate }}
({{ selection.length }})
diff --git a/console/src/app/pages/actions/actions.component.scss b/console/src/app/pages/actions/actions.component.scss
index b4020cfdd..d357d84eb 100644
--- a/console/src/app/pages/actions/actions.component.scss
+++ b/console/src/app/pages/actions/actions.component.scss
@@ -68,6 +68,10 @@ h1 {
align-items: center;
margin-bottom: 0.5rem;
padding-left: 7px;
+
+ .fill-space {
+ flex: 1;
+ }
}
.icon {
diff --git a/console/src/app/pages/actions/actions.component.ts b/console/src/app/pages/actions/actions.component.ts
index c24a74f1c..7d5ac14ca 100644
--- a/console/src/app/pages/actions/actions.component.ts
+++ b/console/src/app/pages/actions/actions.component.ts
@@ -1,7 +1,8 @@
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
-import { Component } from '@angular/core';
+import { Component, OnDestroy } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
+import { Subject, takeUntil } from 'rxjs';
import { ActionKeysType } from 'src/app/modules/action-keys/action-keys.component';
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
@@ -18,13 +19,12 @@ import { AddFlowDialogComponent } from './add-flow-dialog/add-flow-dialog.compon
templateUrl: './actions.component.html',
styleUrls: ['./actions.component.scss'],
})
-export class ActionsComponent {
+export class ActionsComponent implements OnDestroy {
public flow!: Flow.AsObject;
- public flowType: FlowType = FlowType.FLOW_TYPE_EXTERNAL_AUTHENTICATION;
- public typeControl: UntypedFormControl = new UntypedFormControl(FlowType.FLOW_TYPE_EXTERNAL_AUTHENTICATION);
+ public typeControl: UntypedFormControl = new UntypedFormControl();
- public typesForSelection: FlowType[] = [FlowType.FLOW_TYPE_EXTERNAL_AUTHENTICATION];
+ public typesForSelection: FlowType.AsObject[] = [];
public selection: Action.AsObject[] = [];
public InfoSectionType: any = InfoSectionType;
@@ -32,7 +32,7 @@ export class ActionsComponent {
public maxActions: number | null = null;
public ActionState: any = ActionState;
-
+ private destroy$: Subject = new Subject();
constructor(
private mgmtService: ManagementService,
breadcrumbService: BreadcrumbService,
@@ -45,16 +45,42 @@ export class ActionsComponent {
};
breadcrumbService.setBreadcrumb([bread]);
- this.loadFlow();
- }
+ this.getFlowTypes();
- private loadFlow() {
- this.mgmtService.getFlow(this.flowType).then((flowResponse) => {
- if (flowResponse.flow) this.flow = flowResponse.flow;
+ this.typeControl.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
+ this.loadFlow((value as FlowType.AsObject).id);
});
}
- public clearFlow(): void {
+ ngOnDestroy(): void {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
+
+ private getFlowTypes(): Promise {
+ return this.mgmtService
+ .listFlowTypes()
+ .then((resp) => {
+ this.typesForSelection = resp.resultList;
+ if (!this.flow && resp.resultList[0]) {
+ const type = resp.resultList[0];
+ this.typeControl.setValue(type);
+ }
+ })
+ .catch((error: any) => {
+ this.toast.showError(error);
+ });
+ }
+
+ private loadFlow(id: string) {
+ this.mgmtService.getFlow(id).then((flowResponse) => {
+ if (flowResponse.flow) {
+ this.flow = flowResponse.flow;
+ }
+ });
+ }
+
+ public clearFlow(id: string): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.CLEAR',
@@ -68,10 +94,10 @@ export class ActionsComponent {
dialogRef.afterClosed().subscribe((resp) => {
if (resp) {
this.mgmtService
- .clearFlow(this.flowType)
- .then((resp) => {
+ .clearFlow(id)
+ .then(() => {
this.toast.showInfo('FLOWS.FLOWCLEARED', true);
- this.loadFlow();
+ this.loadFlow(id);
})
.catch((error: any) => {
this.toast.showError(error);
@@ -80,11 +106,10 @@ export class ActionsComponent {
});
}
- public openAddTrigger(): void {
+ public openAddTrigger(flow: FlowType.AsObject, trigger?: TriggerType.AsObject): void {
const dialogRef = this.dialog.open(AddFlowDialogComponent, {
data: {
- flowType: this.flowType,
- triggerType: TriggerType.TRIGGER_TYPE_POST_AUTHENTICATION,
+ flowType: flow,
actions: this.selection && this.selection.length ? this.selection : [],
},
width: '400px',
@@ -96,7 +121,7 @@ export class ActionsComponent {
.setTriggerActions(req.getActionIdsList(), req.getFlowType(), req.getTriggerType())
.then((resp) => {
this.toast.showInfo('FLOWS.FLOWCHANGED', true);
- this.loadFlow();
+ this.loadFlow(flow.id);
})
.catch((error: any) => {
this.toast.showError(error);
@@ -111,17 +136,52 @@ export class ActionsComponent {
}
saveFlow(index: number) {
- this.mgmtService
- .setTriggerActions(
- this.flow.triggerActionsList[index].actionsList.map((action) => action.id),
- this.flowType,
- this.flow.triggerActionsList[index].triggerType,
- )
- .then((updateResponse) => {
- this.toast.showInfo('FLOWS.TOAST.ACTIONSSET', true);
- })
- .catch((error) => {
- this.toast.showError(error);
+ if (
+ this.flow.type &&
+ this.flow.triggerActionsList &&
+ this.flow.triggerActionsList[index] &&
+ this.flow.triggerActionsList[index]?.triggerType
+ ) {
+ this.mgmtService
+ .setTriggerActions(
+ this.flow.triggerActionsList[index].actionsList.map((action) => action.id),
+ this.flow.type.id,
+ this.flow.triggerActionsList[index].triggerType?.id ?? '',
+ )
+ .then(() => {
+ this.toast.showInfo('FLOWS.TOAST.ACTIONSSET', true);
+ })
+ .catch((error) => {
+ this.toast.showError(error);
+ });
+ }
+ }
+
+ public removeTriggerActionsList(index: number) {
+ if (this.flow.type && this.flow.triggerActionsList && this.flow.triggerActionsList[index]) {
+ const dialogRef = this.dialog.open(WarnDialogComponent, {
+ data: {
+ confirmKey: 'ACTIONS.CLEAR',
+ cancelKey: 'ACTIONS.CANCEL',
+ titleKey: 'FLOWS.DIALOG.REMOVEACTIONSLIST.TITLE',
+ descriptionKey: 'FLOWS.DIALOG.REMOVEACTIONSLIST.DESCRIPTION',
+ },
+ width: '400px',
});
+
+ dialogRef.afterClosed().subscribe((resp) => {
+ if (resp) {
+ this.mgmtService
+ .setTriggerActions([], this.flow?.type?.id ?? '', this.flow.triggerActionsList[index].triggerType?.id ?? '')
+ .then(() => {
+ this.toast.showInfo('FLOWS.TOAST.ACTIONSSET', true);
+ this.loadFlow(this.flow?.type?.id ?? '');
+ })
+ .catch((error) => {
+ this.toast.showError(error);
+ });
+ }
+ });
+ }
}
}
diff --git a/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.html b/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.html
index eeb89ab2b..63f2df153 100644
--- a/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.html
+++ b/console/src/app/pages/actions/add-flow-dialog/add-flow-dialog.component.html
@@ -2,20 +2,11 @@