44import io .swagger .v3 .oas .annotations .tags .Tag ;
55import org .springframework .http .ResponseEntity ;
66import org .springframework .web .bind .annotation .*;
7+ import tools .dynamia .commons .SimpleCache ;
78import tools .dynamia .commons .StringPojoParser ;
89import tools .dynamia .domain .ValidationError ;
910import tools .dynamia .domain .query .QueryParameters ;
1011import tools .dynamia .domain .services .CrudService ;
12+ import tools .dynamia .integration .Containers ;
13+ import tools .dynamia .viewers .ViewDescriptorFactory ;
1114import tools .jackson .core .JacksonException ;
1215import tools .jackson .databind .json .JsonMapper ;
1316
@@ -46,8 +49,11 @@ public abstract class AbstractCrudServiceRestController {
4649 */
4750 private final JsonMapper mapper = StringPojoParser .createJsonMapper ();
4851
52+ private SimpleCache <String , Class > allowedClasses = new SimpleCache <>();
53+
4954 /**
5055 * Constructs a new {@code CrudServiceRestController} with the given CRUD service.
56+ *
5157 * @param crudService the CRUD service to use
5258 */
5359 public AbstractCrudServiceRestController (CrudService crudService ) {
@@ -56,8 +62,9 @@ public AbstractCrudServiceRestController(CrudService crudService) {
5662
5763 /**
5864 * Creates or updates an entity of the specified class.
65+ *
5966 * @param className the fully qualified class name of the entity
60- * @param json the JSON representation of the entity
67+ * @param json the JSON representation of the entity
6168 * @return the persisted entity
6269 */
6370 @ RequestMapping (method = {RequestMethod .POST , RequestMethod .PUT })
@@ -69,8 +76,9 @@ public ResponseEntity<Object> createOrSave(@PathVariable String className, @Requ
6976
7077 /**
7178 * Deletes an entity by its class name and ID.
79+ *
7280 * @param className the fully qualified class name of the entity
73- * @param id the entity ID
81+ * @param id the entity ID
7482 * @return the deleted entity ID if successful, or 404 if not found
7583 */
7684 @ DeleteMapping ("/{id}" )
@@ -87,8 +95,9 @@ public ResponseEntity<Object> delete(@PathVariable String className, @PathVariab
8795
8896 /**
8997 * Retrieves an entity by its class name and ID.
98+ *
9099 * @param className the fully qualified class name of the entity
91- * @param id the entity ID
100+ * @param id the entity ID
92101 * @return the entity if found, or 404 if not found
93102 */
94103 @ GetMapping ("/{id}" )
@@ -103,7 +112,8 @@ public ResponseEntity<Object> get(@PathVariable String className, @PathVariable
103112
104113 /**
105114 * Finds entities by query parameters.
106- * @param className the fully qualified class name of the entity
115+ *
116+ * @param className the fully qualified class name of the entity
107117 * @param parameters the query parameters
108118 * @return the list of matching entities
109119 */
@@ -116,7 +126,8 @@ public ResponseEntity<List<Object>> find(@PathVariable String className, @Reques
116126
117127 /**
118128 * Gets the ID of an entity by query parameters.
119- * @param className the fully qualified class name of the entity
129+ *
130+ * @param className the fully qualified class name of the entity
120131 * @param parameters the query parameters
121132 * @return the entity ID
122133 */
@@ -129,8 +140,9 @@ public ResponseEntity<Object> getId(@PathVariable String className, @RequestBody
129140
130141 /**
131142 * Parses a JSON string into an entity object of the specified class.
143+ *
132144 * @param className the fully qualified class name
133- * @param json the JSON string
145+ * @param json the JSON string
134146 * @return the entity object
135147 * @throws ValidationError if parsing fails
136148 */
@@ -145,15 +157,29 @@ private Object parseJson(String className, String json) {
145157
146158 /**
147159 * Loads a class by its fully qualified name.
160+ *
148161 * @param className the class name
149162 * @return the {@link Class} object
150163 * @throws ValidationError if the class is not found
151164 */
152165 private Class loadClass (String className ) {
153- try {
154- return Class .forName (className );
155- } catch (ClassNotFoundException e ) {
156- throw new ValidationError ("Class not found " + className + " - " + e .getMessage (), e );
166+ initAllowedClasses ();
167+ Class entityClass = allowedClasses .get (className );
168+ if (entityClass == null ) {
169+ throw new ValidationError ("Class not allowed: " + className );
170+ }
171+ return entityClass ;
172+ }
173+
174+ private void initAllowedClasses () {
175+ if (allowedClasses == null || allowedClasses .isEmpty ()) {
176+ ViewDescriptorFactory viewDescriptorFactory = Containers .get ().findObject (ViewDescriptorFactory .class );
177+ if (viewDescriptorFactory != null ) {
178+ viewDescriptorFactory .findDescriptorsByType ("crud" ).forEach (d -> {
179+ var entityClass = d .getKey ();
180+ allowedClasses .add (entityClass .getName (), entityClass );
181+ });
182+ }
157183 }
158184 }
159185}
0 commit comments