2727import com .cloud .utils .db .Transaction ;
2828import com .cloud .utils .db .TransactionCallback ;
2929import com .cloud .utils .exception .CloudRuntimeException ;
30- import com .google .gson .JsonArray ;
31- import com .google .gson .JsonElement ;
32- import com .google .gson .JsonObject ;
33- import com .google .gson .JsonParser ;
34- import com .google .gson .JsonSyntaxException ;
3530import org .apache .cloudstack .api .ResponseGenerator ;
3631import org .apache .cloudstack .api .command .user .gui .theme .CreateGuiThemeCmd ;
3732import org .apache .cloudstack .api .command .user .gui .theme .ListGuiThemesCmd ;
4338import org .apache .cloudstack .gui .theme .dao .GuiThemeDao ;
4439import org .apache .cloudstack .gui .theme .dao .GuiThemeDetailsDao ;
4540import org .apache .cloudstack .gui .theme .dao .GuiThemeJoinDao ;
41+ import org .apache .cloudstack .gui .theme .json .config .validator .JsonConfigValidator ;
4642import org .apache .commons .lang3 .StringUtils ;
4743import org .apache .logging .log4j .LogManager ;
4844import org .apache .logging .log4j .Logger ;
5248import java .util .ArrayList ;
5349import java .util .Date ;
5450import java .util .List ;
55- import java .util .Map ;
56- import java .util .Set ;
5751
5852@ Component
5953public class GuiThemeServiceImpl implements GuiThemeService {
6054
6155 protected Logger logger = LogManager .getLogger (getClass ());
6256
63- private static final List <String > ALLOWED_PRIMITIVE_PROPERTIES = List .of ("appTitle" , "footer" , "loginFooter" , "logo" , "minilogo" , "banner" );
64-
65- private static final List <String > ALLOWED_ERROR_PROPERTIES = List .of ("403" , "404" , "500" );
66-
67- private static final List <String > ALLOWED_PLUGIN_PROPERTIES = List .of ("name" , "path" , "icon" , "isExternalLink" );
68-
69- private static final String ERROR = "error" ;
70-
71- private static final String PLUGINS = "plugins" ;
72-
7357 @ Inject
7458 GuiThemeDao guiThemeDao ;
7559
@@ -91,6 +75,9 @@ public class GuiThemeServiceImpl implements GuiThemeService {
9175 @ Inject
9276 DomainDao domainDao ;
9377
78+ @ Inject
79+ JsonConfigValidator jsonConfigValidator ;
80+
9481 @ Override
9582 public ListResponse <GuiThemeResponse > listGuiThemes (ListGuiThemesCmd cmd ) {
9683 ListResponse <GuiThemeResponse > response = new ListResponse <>();
@@ -244,94 +231,7 @@ protected void validateParameters(String jsonConfig, String domainIds, String ac
244231
245232 validateObjectUuids (accountIds , Account .class );
246233 validateObjectUuids (domainIds , Domain .class );
247- validateJsonConfiguration (jsonConfig );
248- }
249-
250- protected void validateJsonConfiguration (String jsonConfig ) {
251- if (jsonConfig == null ) {
252- return ;
253- }
254-
255- JsonObject jsonObject = new JsonObject ();
256-
257- try {
258- JsonElement jsonElement = new JsonParser ().parse (jsonConfig );
259- Set <Map .Entry <String , JsonElement >> entries = jsonElement .getAsJsonObject ().entrySet ();
260- entries .stream ().forEach (entry -> validateJsonAttributes (entry , jsonObject ));
261- } catch (JsonSyntaxException exception ) {
262- logger .error ("The following exception was thrown while parsing the JSON object: [{}]." , exception .getMessage ());
263- throw new CloudRuntimeException ("Specified JSON configuration is not a valid JSON object." );
264- }
265- }
266-
267- /**
268- * Validates the informed JSON attributes considering the allowed properties by the API, any invalid option is ignored.
269- * All valid options are added to a {@link JsonObject} that will be considered as the final JSON configuration used by the GUI theme.
270- */
271- private void validateJsonAttributes (Map .Entry <String , JsonElement > entry , JsonObject jsonObject ) {
272- JsonElement entryValue = entry .getValue ();
273- String entryKey = entry .getKey ();
274-
275- if (entryValue .isJsonPrimitive () && ALLOWED_PRIMITIVE_PROPERTIES .contains (entryKey )) {
276- logger .trace ("The JSON attribute [{}] is a valid option." , entryKey );
277- jsonObject .add (entryKey , entryValue );
278- } else if (entryValue .isJsonObject () && ERROR .equals (entryKey )) {
279- validateErrorAttribute (entry , jsonObject );
280- } else if (entryValue .isJsonArray () && PLUGINS .equals (entryKey )) {
281- validatePluginsAttribute (entry , jsonObject );
282- } else {
283- warnOfInvalidJsonAttribute (entryKey );
284- }
285- }
286-
287- /**
288- * Creates a {@link JsonObject} with only the valid options for the Plugins' properties specified in the {@link #ALLOWED_PLUGIN_PROPERTIES}.
289- */
290- protected void validatePluginsAttribute (Map .Entry <String , JsonElement > entry , JsonObject jsonObject ) {
291- Set <Map .Entry <String , JsonElement >> entries = entry .getValue ().getAsJsonArray ().get (0 ).getAsJsonObject ().entrySet ();
292- JsonObject objectToBeAdded = createJsonObject (entries , ALLOWED_PLUGIN_PROPERTIES );
293- JsonArray jsonArray = new JsonArray ();
294-
295- if (objectToBeAdded .entrySet ().isEmpty ()) {
296- return ;
297- }
298-
299- jsonArray .add (objectToBeAdded );
300- jsonObject .add (entry .getKey (), jsonArray );
301- }
302-
303- /**
304- * Creates a {@link JsonObject} with only the valid options for the Error's properties specified in the {@link #ALLOWED_ERROR_PROPERTIES}.
305- */
306- protected void validateErrorAttribute (Map .Entry <String , JsonElement > entry , JsonObject jsonObject ) {
307- Set <Map .Entry <String , JsonElement >> entries = entry .getValue ().getAsJsonObject ().entrySet ();
308- JsonObject objectToBeAdded = createJsonObject (entries , ALLOWED_ERROR_PROPERTIES );
309-
310- if (objectToBeAdded .entrySet ().isEmpty ()) {
311- return ;
312- }
313-
314- jsonObject .add (entry .getKey (), objectToBeAdded );
315- }
316-
317- protected JsonObject createJsonObject (Set <Map .Entry <String , JsonElement >> entries , List <String > allowedProperties ) {
318- JsonObject objectToBeAdded = new JsonObject ();
319-
320- for (Map .Entry <String , JsonElement > recursiveEntry : entries ) {
321- String entryKey = recursiveEntry .getKey ();
322-
323- if (!allowedProperties .contains (entryKey )) {
324- warnOfInvalidJsonAttribute (entryKey );
325- continue ;
326- }
327- objectToBeAdded .add (entryKey , recursiveEntry .getValue ());
328- }
329-
330- return objectToBeAdded ;
331- }
332-
333- protected void warnOfInvalidJsonAttribute (String entryKey ) {
334- logger .warn ("The JSON attribute [{}] is not a valid option, therefore, it will be ignored." , entryKey );
234+ jsonConfigValidator .validateJsonConfiguration (jsonConfig );
335235 }
336236
337237 /**
0 commit comments