diff --git a/engine/src/main/resources/liquibase/changeSetPort.xml b/engine/src/main/resources/liquibase/changeSetPort.xml
index 95140223cb..4692adaa69 100644
--- a/engine/src/main/resources/liquibase/changeSetPort.xml
+++ b/engine/src/main/resources/liquibase/changeSetPort.xml
@@ -27,5 +27,6 @@
+
\ No newline at end of file
diff --git a/engine/src/main/resources/liquibase/port/20230626000000_mfe_communication_mediator_object.xml b/engine/src/main/resources/liquibase/port/20230626000000_mfe_communication_mediator_object.xml
index 490b1a109c..a98a66efa0 100644
--- a/engine/src/main/resources/liquibase/port/20230626000000_mfe_communication_mediator_object.xml
+++ b/engine/src/main/resources/liquibase/port/20230626000000_mfe_communication_mediator_object.xml
@@ -5,7 +5,7 @@
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.4.xsd">
-
+
diff --git a/engine/src/main/resources/liquibase/port/20231027000000_update_profile_types.xml b/engine/src/main/resources/liquibase/port/20231027000000_update_profile_types.xml
new file mode 100644
index 0000000000..8933e74ba1
--- /dev/null
+++ b/engine/src/main/resources/liquibase/port/20231027000000_update_profile_types.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ item='userProfileTypes'
+
+
+
+
diff --git a/engine/src/main/resources/liquibase/port/clob/production/sysconfig_3_1.xml b/engine/src/main/resources/liquibase/port/clob/production/sysconfig_3_1.xml
new file mode 100644
index 0000000000..f8a07440dd
--- /dev/null
+++ b/engine/src/main/resources/liquibase/port/clob/production/sysconfig_3_1.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ true
+
+
+
+ userprofile:fullname
+
+
+
+
+ true
+
+
+ userprofile:email
+
+
+
+
+ userprofile:profilepicture
+
+
+
+
+
\ No newline at end of file
diff --git a/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_type_regex.json b/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_type_regex.json
new file mode 100644
index 0000000000..95e790ac47
--- /dev/null
+++ b/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_type_regex.json
@@ -0,0 +1,19 @@
+{
+ "code": "RX2",
+ "name": "Profile Type RX2",
+ "attributes": [
+ {
+ "code": "fullname",
+ "type": "Monotext",
+ "name": "Description of full name attribute",
+ "mandatory": false,
+ "validationRules": {
+ "regex":"^(?=.{2,70}$)[a-zA-ZÀ-ÿ0-9_-]{1}[a-zA-ZÀ-ÿ0-9 _-]*[a-zA-ZÀ-ÿ0-9_-]{1}$"
+ },
+ "roles": [{
+ "code": "userprofile:fullname",
+ "descr": "The Attribute containing the full name"
+ }]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_valid.json b/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_valid.json
new file mode 100644
index 0000000000..7d6746516d
--- /dev/null
+++ b/engine/src/test/java/org/entando/entando/web/userprofile/13_POST_valid.json
@@ -0,0 +1,17 @@
+{
+ "id": "new_user",
+ "typeCode": "RX2",
+ "typeDescription": "Type for test",
+ "description": "Profile of user",
+ "mainGroup": "free",
+ "groups": [
+ "group1",
+ "group2"
+ ],
+ "attributes": [
+ {
+ "code": "fullname",
+ "value": "Name"
+ }
+ ]
+}
diff --git a/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_invalid.json b/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_invalid.json
new file mode 100644
index 0000000000..4a9e90da46
--- /dev/null
+++ b/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_invalid.json
@@ -0,0 +1,17 @@
+{
+ "id": "new_user",
+ "typeCode": "RX2",
+ "typeDescription": "Type for test RX2",
+ "description": "Profile of user",
+ "mainGroup": "free",
+ "groups": [
+ "group1",
+ "group2"
+ ],
+ "attributes": [
+ {
+ "code": "fullname",
+ "value": "John Doe. "
+ }
+ ]
+}
diff --git a/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_valid.json b/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_valid.json
new file mode 100644
index 0000000000..a39fe77ad4
--- /dev/null
+++ b/engine/src/test/java/org/entando/entando/web/userprofile/13_PUT_valid.json
@@ -0,0 +1,17 @@
+{
+ "id": "new_user",
+ "typeCode": "RX2",
+ "typeDescription": "Type for test RX2",
+ "description": "Profile of user",
+ "mainGroup": "free",
+ "groups": [
+ "group1",
+ "group2"
+ ],
+ "attributes": [
+ {
+ "code": "fullname",
+ "value": "John Doe"
+ }
+ ]
+}
diff --git a/engine/src/test/java/org/entando/entando/web/userprofile/UserProfileControllerIntegrationTest.java b/engine/src/test/java/org/entando/entando/web/userprofile/UserProfileControllerIntegrationTest.java
index 4dd91d152d..3569cd2e64 100644
--- a/engine/src/test/java/org/entando/entando/web/userprofile/UserProfileControllerIntegrationTest.java
+++ b/engine/src/test/java/org/entando/entando/web/userprofile/UserProfileControllerIntegrationTest.java
@@ -42,6 +42,7 @@
import java.util.Arrays;
import java.util.Date;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -531,6 +532,75 @@ void testAddUserProfileWithProfilePicture() throws Exception {
}
}
+ @Test
+ void testPutMyProfileRegexAccept() throws Exception {
+ try {
+ Assertions.assertNull(this.userProfileManager.getEntityPrototype("RX2"));
+ String accessToken = this.createAccessToken();
+
+ this.executeProfileTypePost("13_POST_type_regex.json", accessToken, status().isOk());
+
+ Assertions.assertNotNull(this.userProfileManager.getEntityPrototype("RX2"));
+
+ this.executeProfilePost("13_POST_valid.json", accessToken, status().isOk()).andDo(resultPrint())
+ .andExpect(jsonPath("$.payload.id", is("new_user")))
+ .andExpect(jsonPath("$.errors.size()", is(0)))
+ .andExpect(jsonPath("$.metaData.size()", is(0)));
+
+ UserDetails userEditMyProfile = new OAuth2TestUtils.UserBuilder("new_user", "0x24")
+ .withAuthorization(Group.FREE_GROUP_NAME, "editor", Permission.ENTER_BACKEND)
+ .build();
+ String userEditMyProfileToken = mockOAuthInterceptor(userEditMyProfile);
+
+ this.executePutUpdateMyProfile("13_PUT_valid.json", userEditMyProfile, userEditMyProfileToken,
+ status().isOk())
+ .andExpect(jsonPath("$.payload.id", is("new_user")))
+ .andExpect(jsonPath("$.payload.typeCode", is("RX2")))
+ .andExpect(jsonPath("$.payload.typeDescription", is("Type for test RX2")));
+
+ } finally {
+ this.userManager.removeUser("new_user");
+ if (null != this.userProfileManager.getEntityPrototype("RX2")) {
+ ((IEntityTypesConfigurer) this.userProfileManager).removeEntityPrototype("RX2");
+ }
+ Assertions.assertNull(this.userProfileManager.getEntityPrototype("RX2"));
+ }
+ }
+
+ @Test
+ void testPutMyProfileRegexReject() throws Exception {
+ try {
+ Assertions.assertNull(this.userProfileManager.getEntityPrototype("RX2"));
+ String accessToken = this.createAccessToken();
+
+ this.executeProfileTypePost("13_POST_type_regex.json", accessToken, status().isOk());
+
+ Assertions.assertNotNull(this.userProfileManager.getEntityPrototype("RX2"));
+
+ this.executeProfilePost("13_POST_valid.json", accessToken, status().isOk()).andDo(resultPrint())
+ .andExpect(jsonPath("$.payload.id", is("new_user")))
+ .andExpect(jsonPath("$.errors.size()", is(0)))
+ .andExpect(jsonPath("$.metaData.size()", is(0)));
+
+ UserDetails userEditMyProfile = new OAuth2TestUtils.UserBuilder("new_user", "0x24")
+ .withAuthorization(Group.FREE_GROUP_NAME, "editor", Permission.ENTER_BACKEND)
+ .build();
+ String userEditMyProfileToken = mockOAuthInterceptor(userEditMyProfile);
+
+ this.executePutUpdateMyProfile("13_PUT_invalid.json", userEditMyProfile, userEditMyProfileToken,
+ status().isBadRequest())
+ .andExpect(jsonPath("$.errors.size()", is(1)))
+ .andExpect(jsonPath("$.errors[0].message",
+ containsString("Attribute 'fullname' Invalid format")));
+ } finally {
+ this.userManager.removeUser("new_user");
+ if (null != this.userProfileManager.getEntityPrototype("RX2")) {
+ ((IEntityTypesConfigurer) this.userProfileManager).removeEntityPrototype("RX2");
+ }
+ Assertions.assertNull(this.userProfileManager.getEntityPrototype("RX2"));
+ }
+ }
+
private String createAccessToken() throws Exception {
UserDetails user = new OAuth2TestUtils.UserBuilder("jack_bauer", "0x24")
.withAuthorization(Group.FREE_GROUP_NAME, "manageUserProfile", Permission.MANAGE_USER_PROFILES)