8
8
import io .kestra .core .models .dashboards .charts .DataChart ;
9
9
import io .kestra .core .models .dashboards .charts .DataChartKPI ;
10
10
import io .kestra .core .models .flows .Flow ;
11
+ import io .kestra .core .models .validations .ManualConstraintViolation ;
11
12
import io .kestra .core .models .validations .ModelValidator ;
12
13
import io .kestra .core .models .validations .ValidateConstraintViolation ;
13
14
import io .kestra .core .repositories .ArrayListTotal ;
14
15
import io .kestra .core .repositories .DashboardRepositoryInterface ;
15
16
import io .kestra .core .repositories .FlowRepositoryInterface ;
16
17
import io .kestra .core .serializers .YamlParser ;
17
18
import io .kestra .core .tenant .TenantService ;
18
- import io .kestra .core .utils .IdUtils ;
19
19
import io .kestra .plugin .core .dashboard .chart .Markdown ;
20
20
import io .kestra .plugin .core .dashboard .chart .Table ;
21
21
import io .kestra .plugin .core .dashboard .chart .mardown .sources .FlowDescription ;
49
49
import java .io .OutputStreamWriter ;
50
50
import java .time .Duration ;
51
51
import java .time .ZonedDateTime ;
52
- import java .util .List ;
53
- import java .util .Map ;
54
- import java .util .Optional ;
52
+ import java .util .*;
53
+ import java .util .regex .Pattern ;
55
54
56
55
import static io .kestra .core .utils .DateUtils .validateTimeline ;
57
56
60
59
@ Slf4j
61
60
public class DashboardController {
62
61
protected static final YamlParser YAML_PARSER = new YamlParser ();
62
+ public static final Pattern DASHBOARD_ID_PATTERN = Pattern .compile ("^id:.*$" , Pattern .MULTILINE );
63
63
64
64
@ Inject
65
65
private DashboardRepositoryInterface dashboardRepository ;
@@ -91,7 +91,12 @@ public PagedResults<Dashboard> searchDashboards(
91
91
public Dashboard getDashboard (
92
92
@ Parameter (description = "The dashboard id" ) @ PathVariable String id
93
93
) throws ConstraintViolationException {
94
- return dashboardRepository .get (tenantService .resolveTenant (), id ).orElse (null );
94
+ return dashboardRepository .get (tenantService .resolveTenant (), id ).map (d -> {
95
+ if (!DASHBOARD_ID_PATTERN .matcher (d .getSourceCode ()).matches ()) {
96
+ return d .toBuilder ().sourceCode ("id: " + d .getId () + "\n " + d .getSourceCode ()).build ();
97
+ }
98
+ return d ;
99
+ }).orElse (null );
95
100
}
96
101
97
102
@ ExecuteOn (TaskExecutors .IO )
@@ -101,13 +106,24 @@ public HttpResponse<Dashboard> createDashboard(
101
106
@ RequestBody (description = "The dashboard definition as YAML" ) @ Body String dashboard
102
107
) throws ConstraintViolationException {
103
108
Dashboard dashboardParsed = parseDashboard (dashboard );
109
+
110
+ if (dashboardParsed .getId () == null ) {
111
+ throw new IllegalArgumentException ("Dashboard id is mandatory" );
112
+ }
104
113
modelValidator .validate (dashboardParsed );
105
114
106
- if (dashboardParsed .getId () != null ) {
107
- throw new IllegalArgumentException ("Dashboard id is not editable" );
115
+ Optional <Dashboard > existingDashboard = dashboardRepository .get (tenantService .resolveTenant (), dashboardParsed .getId ());
116
+ if (existingDashboard .isPresent ()) {
117
+ throw new ConstraintViolationException (Collections .singleton (ManualConstraintViolation .of (
118
+ "Dashboard id already exists" ,
119
+ dashboardParsed ,
120
+ Dashboard .class ,
121
+ "dashboard.id" ,
122
+ dashboardParsed .getId ()
123
+ )));
108
124
}
109
125
110
- return HttpResponse .ok (this .save (null , dashboardParsed . toBuilder (). id ( IdUtils . create ()). build () , dashboard ));
126
+ return HttpResponse .ok (this .save (null , dashboardParsed , dashboard ));
111
127
}
112
128
113
129
@ ExecuteOn (TaskExecutors .IO )
@@ -148,6 +164,15 @@ public HttpResponse<Dashboard> updateDashboard(
148
164
return HttpResponse .status (HttpStatus .NOT_FOUND );
149
165
}
150
166
Dashboard dashboardToSave = parseDashboard (dashboard );
167
+ if (!dashboardToSave .getId ().equals (id )) {
168
+ throw new ConstraintViolationException (Set .of (ManualConstraintViolation .of (
169
+ "Illegal dashboard id update" ,
170
+ dashboardToSave ,
171
+ Dashboard .class ,
172
+ "dashboard.id" ,
173
+ dashboardToSave .getId ()
174
+ )));
175
+ }
151
176
modelValidator .validate (dashboardToSave );
152
177
153
178
return HttpResponse .ok (this .save (existingDashboard .get (), dashboardToSave , dashboard ));
0 commit comments