From 5b3f0a13e25cd842e0bbd4be3d21eb48ab1d108f Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Tue, 17 May 2022 16:51:18 +0530 Subject: [PATCH 1/3] feat(jans-config-api): user custom attributes at root level - 1348 --- agama/.gitignore | 35 ++++ .../docs/jans-config-api-swagger.yaml | 6 + .../configapi/plugin/mgt/model/user/User.java | 57 ++++++ .../plugin/mgt/rest/UserResource.java | 9 +- .../plugin/mgt/service/UserService.java | 75 ++++++-- .../io/jans/configapi/core/util/DataUtil.java | 176 ++++++++++++++++++ 6 files changed, 341 insertions(+), 17 deletions(-) create mode 100644 agama/.gitignore create mode 100644 jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java create mode 100644 jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java diff --git a/agama/.gitignore b/agama/.gitignore new file mode 100644 index 00000000000..92e4596b0a6 --- /dev/null +++ b/agama/.gitignore @@ -0,0 +1,35 @@ +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +release.properties diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 0f11d15b908..0b23929e19c 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -6697,6 +6697,12 @@ components: dn: type: string description: Domain name. + baseDN: + type: string + description: Base DN for the User entity + status: + type: string + description: User status userId: description: A domain issued and managed identifier for the user. type: string diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java new file mode 100644 index 00000000000..19eb13aa505 --- /dev/null +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java @@ -0,0 +1,57 @@ +package io.jans.configapi.plugin.mgt.model.user; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.jans.orm.model.base.CustomObjectAttribute; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class User extends io.jans.as.common.model.common.User { + + private static final long serialVersionUID = 1L; + + private String mail; + private String displayName; + private String jansStatus; + private String givenName; + private String userPassword; + + public String getMail() { + return mail; + } + public void setMail(String mail) { + this.mail = mail; + } + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + public String getJansStatus() { + return jansStatus; + } + public void setJansStatus(String jansStatus) { + this.jansStatus = jansStatus; + } + public String getGivenName() { + return givenName; + } + public void setGivenName(String givenName) { + this.givenName = givenName; + } + public String getUserPassword() { + return userPassword; + } + public void setUserPassword(String userPassword) { + this.userPassword = userPassword; + } + @Override + public String toString() { + return "User [mail=" + mail + ", displayName=" + displayName + ", jansStatus=" + jansStatus + ", givenName=" + + givenName + ", userPassword= XXXXX ]"; + } + + +} diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java index b44658cd1b2..d0e54eab42a 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java @@ -4,11 +4,10 @@ import com.github.fge.jsonpatch.JsonPatchException; import static io.jans.as.model.util.Util.escapeLog; -import io.jans.as.common.model.common.User; +import io.jans.configapi.plugin.mgt.model.user.User; import io.jans.as.common.service.common.EncryptionService; import io.jans.configapi.core.rest.BaseResource; import io.jans.configapi.core.rest.ProtectedApi; -import io.jans.configapi.plugin.mgt.model.config.UserMgtConfigSource; import io.jans.configapi.plugin.mgt.model.user.UserPatchRequest; import io.jans.configapi.plugin.mgt.service.UserService; import io.jans.configapi.plugin.mgt.util.Constants; @@ -94,7 +93,7 @@ public Response getUserByInum(@PathParam(ApiConstants.INUM) @NotNull String inum return Response.ok(decryptUserPassword(user)).build(); } - +/* @POST @ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS }) public Response createUser(@Valid User user) @@ -171,6 +170,8 @@ public Response deleteUser(@PathParam(ApiConstants.INUM) @NotNull String inum) { return Response.noContent().build(); } + */ + private List doSearch(SearchRequest searchReq) throws IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { logger.debug("User search params - searchReq:{} ", escapeLog(searchReq)); @@ -236,6 +237,6 @@ private User decryptUserPassword(User user) throws EncryptionException { } return user; } - + } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java index 9fba435288a..7ebaf2b77ba 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java @@ -1,17 +1,19 @@ package io.jans.configapi.plugin.mgt.service; import com.github.fge.jsonpatch.JsonPatchException; -import io.jans.as.common.model.common.User; +import io.jans.configapi.plugin.mgt.model.user.User; import io.jans.as.common.util.AttributeConstants; import io.jans.as.model.config.StaticConfiguration; import io.jans.as.model.configuration.AppConfiguration; import io.jans.configapi.core.util.Jackson; import io.jans.configapi.plugin.mgt.model.user.UserPatchRequest; import io.jans.configapi.core.model.SearchRequest; +import io.jans.configapi.core.util.DataUtil; import io.jans.configapi.util.AuthUtil; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SortOrder; import io.jans.orm.model.base.CustomObjectAttribute; +import io.jans.orm.reflect.property.Setter; import io.jans.orm.search.filter.Filter; import io.jans.util.StringHelper; @@ -78,12 +80,27 @@ public PagedResult searchUsers(SearchRequest searchRequest) { searchRequest.getStartIndex() - 1, searchRequest.getCount(), searchRequest.getMaxCount()); } + + public User getUserBasedOnInum(String inum) { + User result = null; + try { + io.jans.as.common.model.common.User user = getUserByInum(inum); + result = getConfigUser(user); + } catch (Exception ex) { + logger.error("Failed to load user entry", ex); + } + return result; + } + + private User getConfigUser(io.jans.as.common.model.common.User user) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return populateConfigUser(user); + } public void removeUser(User user) { persistenceEntryManager.removeRecursively(user.getDn(), User.class); } - public User patchUser(String inum, UserPatchRequest userPatchRequest) throws JsonPatchException, IOException { + public io.jans.as.common.model.common.User patchUser(String inum, UserPatchRequest userPatchRequest) throws JsonPatchException, IOException { if (logger.isDebugEnabled()) { logger.debug("Details to patch user inum:{}, UserPatchRequest:{} ", escapeLog(inum), escapeLog(userPatchRequest)); @@ -92,7 +109,7 @@ public User patchUser(String inum, UserPatchRequest userPatchRequest) throws Jso return null; } - User user = getUserByInum(inum); + io.jans.as.common.model.common.User user = getUserByInum(inum); if (user == null) { return null; } @@ -119,17 +136,9 @@ public User patchUser(String inum, UserPatchRequest userPatchRequest) throws Jso } - public User getUserBasedOnInum(String inum) { - User result = null; - try { - result = getUserByInum(inum); - } catch (Exception ex) { - logger.error("Failed to load user entry", ex); - } - return result; - } + - private User updateCustomAttributes(User user, List customAttributes) { + private io.jans.as.common.model.common.User updateCustomAttributes(io.jans.as.common.model.common.User user, List customAttributes) { logger.debug("Custom Attributes to update for - user:{}, customAttributes:{} ", user, customAttributes); if (customAttributes == null || customAttributes.isEmpty()) { @@ -221,6 +230,7 @@ public String getUserExclusionAttributesAsString() { return authUtil.getUserExclusionAttributesAsString(); } + public String checkMandatoryFields(User user) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { List mandatoryAttributes = authUtil.getUserMandatoryAttributes(); @@ -262,4 +272,43 @@ public String checkMandatoryFields(User user) return missingAttributes.toString(); } + private User populateConfigUser(io.jans.as.common.model.common.User user) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException + { + List mandatoryAttributes = authUtil.getUserMandatoryAttributes(); + logger.debug("mandatoryAttributess :{} ", mandatoryAttributes); + + User userConfig = (User) user; + StringBuilder missingAttributes = new StringBuilder(); + if (mandatoryAttributes == null || mandatoryAttributes.isEmpty()) { + return userConfig; + } + + List allFields = authUtil.getAllFields(user.getClass()); + logger.debug("All user fields :{} ", allFields); + + Object attributeValue = null; + for (String attribute : mandatoryAttributes) { + logger.debug("User class allFields:{} conatins attribute:{} ? :{} ", allFields, attribute, + authUtil.containsField(allFields, attribute)); + if (authUtil.containsField(allFields, attribute)) { + logger.debug("Checking if attribute:{} is simple attribute", attribute); + attributeValue = BeanUtils.getProperty(user, attribute); + logger.debug("User basic attribute:{} - attributeValue:{} ", attribute, attributeValue); + } else { + logger.debug("Checking if attribute:{} is custom attribute", attribute); + attributeValue = user.getAttribute(attribute); + logger.debug("User custom attribute:{} - attributeValue:{} ", attribute, attributeValue); + } + + //set attribute + Setter setterMethod = DataUtil.getSetterMethod(userConfig.getClass(), attribute); + Object propertyValue = setterMethod.getMethod().invoke(userConfig, attributeValue); + logger.error("After setterMethod invoked attribute:{}, propertyValue:{} ", attribute, propertyValue); + }//for + logger.debug("Checking mandatory userConfig:{} ", userConfig); + + logger.debug("Returning missingAttributes:{} ", missingAttributes); + + return userConfig; + } } diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java new file mode 100644 index 00000000000..db1491e46e0 --- /dev/null +++ b/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java @@ -0,0 +1,176 @@ +package io.jans.configapi.core.util; + +import io.jans.as.model.json.JsonApplier; +import io.jans.orm.exception.MappingException; +import io.jans.orm.reflect.property.Getter; +import io.jans.orm.reflect.property.Setter; +import io.jans.orm.reflect.util.ReflectHelper; + +import jakarta.enterprise.context.ApplicationScoped; +import java.beans.Introspector; +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class DataUtil { + + private DataUtil() { + } + + private static final Logger logger = LoggerFactory.getLogger(DataUtil.class); + + public static Class getPropertType(String className, String name) throws MappingException { + logger.error("className:{} , name:{} ", className, name); + return ReflectHelper.reflectedPropertyClass(className, name); + + } + + public static Getter getGetterMethod(Class clazz, String name) throws MappingException { + logger.error("Get Getter fromclazz:{} , name:{} ", clazz, name); + return ReflectHelper.getGetter(clazz, name); + } + + public static Setter getSetterMethod(Class clazz, String name) throws MappingException { + logger.error("Get Setter from clazz:{} for name:{} ", clazz, name); + return ReflectHelper.getSetter(clazz, name); + } + + public static Object getValue(Object object, String property) throws MappingException { + logger.error("Get value from object:{} for property:{} ", object, property); + return ReflectHelper.getValue(object, property); + } + + public static Method getSetter(String fieldName, Class clazz) throws Exception { + PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); + for (PropertyDescriptor p : props) + if (p.getName().equals(fieldName)) + return p.getWriteMethod(); + return null; + } + + public Object invokeReflectionGetter(Object obj, String variableName) { + try { + PropertyDescriptor pd = new PropertyDescriptor(variableName, obj.getClass()); + Method getter = pd.getReadMethod(); + if (getter != null) { + return getter.invoke(obj); + } else { + logger.error(String.format("Getter Method not found for class: %s property: %s", + obj.getClass().getName(), variableName)); + } + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | IntrospectionException e) { + logger.error(String.format("Getter Method ERROR for class: %s property: %s", obj.getClass().getName(), + variableName), e); + } + return null; + } + + public static void invokeReflectionSetter(Object obj, String propertyName, Object variableValue) { + PropertyDescriptor pd; + try { + pd = new PropertyDescriptor(propertyName, obj.getClass()); + Method method = pd.getWriteMethod(); + if (method != null) { + method.invoke(obj, variableValue); + } else { + logger.error(String.format(" Setter Method not found for class: %s property: %s", + obj.getClass().getName(), propertyName)); + } + } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + logger.error(String.format("\n\n Setter Method invocation ERROR for class: %s property: %s", + obj.getClass().getName(), propertyName), e); + } + } + + public static boolean containsField(List allFields, String attribute) { + logger.error("allFields:{}, attribute:{}, allFields.contains(attribute):{} ", allFields, attribute, + allFields.stream().anyMatch(f -> f.getName().equals(attribute))); + + return allFields.stream().anyMatch(f -> f.getName().equals(attribute)); + } + + public static List getAllFields(Class type) { + List allFields = new ArrayList<>(); + allFields = getAllFields(allFields, type); + logger.error("Fields:{} of type:{} ", allFields, type); + + return allFields; + } + + public static List getAllFields(List fields, Class type) { + logger.error("Getting fields type:{} - fields:{} ", type, fields); + fields.addAll(Arrays.asList(type.getDeclaredFields())); + + if (type.getSuperclass() != null) { + getAllFields(fields, type.getSuperclass()); + } + logger.error("Final fields:{} of type:{} ", fields, type); + return fields; + } + + public static Map getFieldTypeMap(Class clazz) { + logger.error("clazz:{} ", clazz); + Map propertyTypeMap = new HashMap<>(); + + if (clazz == null) { + return propertyTypeMap; + } + + List fields = getAllFields(clazz); + logger.error("fields:{} ", fields); + + for (Field field : fields) { + logger.error( + "field:{} , field.getAnnotatedType():{}, field.getAnnotations():{} , field.getType().getAnnotations():{}, field.getType().getCanonicalName():{} , field.getType().getClass():{} , field.getType().getClasses():{} , field.getType().getComponentType():{}", + field, field.getAnnotatedType(), field.getAnnotations(), field.getType().getAnnotations(), + field.getType().getCanonicalName(), field.getType().getClass(), field.getType().getClasses(), + field.getType().getComponentType()); + propertyTypeMap.put(field.getName(), field.getType().getSimpleName()); + } + logger.error("Final propertyTypeMap{} ", propertyTypeMap); + return propertyTypeMap; + } + + public static Map getPropertyTypeMap(Class clazz) { + logger.error("clazz:{} for getting property and field map ", clazz); + Map propertyTypeMap = new HashMap<>(); + if (clazz == null) { + return propertyTypeMap; + } + logger.error("clazz.getCanonicalName():{}, clazz.getName():{}, clazz.getPackageName():{} ", + clazz.getCanonicalName(), clazz.getName(), clazz.getPackageName()); + String className = clazz.getName(); + List fields = getAllFields(clazz); + logger.error("fields:{} ", fields); + if (fields == null) { + return propertyTypeMap; + } + for (Field field : fields) { + logger.error("field:{} ", field); + Class dataTypeClass = getPropertType(className, field.getName()); + logger.error("dataTypeClass:{} ", dataTypeClass); + propertyTypeMap.put(field, dataTypeClass); + } + + logger.error("Final propertyTypeMap{} ", propertyTypeMap); + return propertyTypeMap; + } + + public static Object invokeGetterMethod(Object obj, String variableName) { + return JsonApplier.getInstance().invokeReflectionGetter(obj, variableName); + } + +} From 40570a7b9d2d03358cbfb0d8c3964a4111e15bb5 Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Tue, 17 May 2022 22:12:43 +0530 Subject: [PATCH 2/3] feat(jans-config-api): exposed attributes at root value --- .../docs/jans-config-api-swagger.yaml | 28 ++- .../model/user/{User.java => CustomUser.java} | 9 +- .../plugin/mgt/rest/UserResource.java | 174 +++++++++++++++--- .../plugin/mgt/service/UserService.java | 75 ++------ 4 files changed, 180 insertions(+), 106 deletions(-) rename jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/{User.java => CustomUser.java} (83%) diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 0b23929e19c..4c454384deb 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -2448,7 +2448,7 @@ paths: title: Users. description: List of users. items: - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' '401': $ref: '#/components/responses/Unauthorized' '500': @@ -2500,7 +2500,7 @@ paths: schema: title: User Details. description: User Details. - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' responses: '201': description: Created @@ -2508,7 +2508,7 @@ paths: application/json: schema: title: User Details. - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' '401': $ref: '#/components/responses/Unauthorized' '500': @@ -2526,7 +2526,7 @@ paths: application/json: schema: title: User Details. - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' responses: '200': description: OK @@ -2534,7 +2534,7 @@ paths: application/json: schema: title: User Details. - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' '401': $ref: '#/components/responses/Unauthorized' '404': @@ -2563,7 +2563,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' '401': $ref: '#/components/responses/Unauthorized' '500': @@ -2608,7 +2608,7 @@ paths: application/json: schema: title: User Details. - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/CustomUser' '401': $ref: '#/components/responses/Unauthorized' '404': @@ -6687,7 +6687,7 @@ components: $ref: '#/components/schemas/FacterData' description: Underlying Server stats - User: + CustomUser: title: User object description: User. type: object @@ -6724,6 +6724,18 @@ components: type: array items: $ref: '#/components/schemas/CustomAttribute' + mail: + type: string + description: User mail + displayName: + type: string + description: Name of the user suitable for display to end-users + givenName: + type: string + description: User given Name + userPassword: + type: string + description: User password UserPatchRequest: title: User Patch Request object diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java similarity index 83% rename from jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java rename to jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java index 19eb13aa505..12fc969787b 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/User.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/model/user/CustomUser.java @@ -2,12 +2,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import io.jans.orm.model.base.CustomObjectAttribute; - -import java.util.List; +import io.jans.as.common.model.common.User; @JsonIgnoreProperties(ignoreUnknown = true) -public class User extends io.jans.as.common.model.common.User { +public class CustomUser extends User { private static final long serialVersionUID = 1L; @@ -49,9 +47,8 @@ public void setUserPassword(String userPassword) { } @Override public String toString() { - return "User [mail=" + mail + ", displayName=" + displayName + ", jansStatus=" + jansStatus + ", givenName=" + return "CustomUser [mail=" + mail + ", displayName=" + displayName + ", jansStatus=" + jansStatus + ", givenName=" + givenName + ", userPassword= XXXXX ]"; } - } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java index d0e54eab42a..ab3ea6d55e2 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java @@ -1,13 +1,13 @@ package io.jans.configapi.plugin.mgt.rest; - import com.github.fge.jsonpatch.JsonPatchException; import static io.jans.as.model.util.Util.escapeLog; -import io.jans.configapi.plugin.mgt.model.user.User; +import io.jans.as.common.model.common.User; import io.jans.as.common.service.common.EncryptionService; import io.jans.configapi.core.rest.BaseResource; import io.jans.configapi.core.rest.ProtectedApi; +import io.jans.configapi.plugin.mgt.model.user.CustomUser; import io.jans.configapi.plugin.mgt.model.user.UserPatchRequest; import io.jans.configapi.plugin.mgt.service.UserService; import io.jans.configapi.plugin.mgt.util.Constants; @@ -40,14 +40,18 @@ public class UserResource extends BaseResource { private static final String USER = "user"; + private static final String MAIL = "mail"; + private static final String DISPLAY_NAME = "displayName"; + private static final String JANS_STATUS = "jansStatus"; + private static final String GIVEN_NAME = "givenName"; private static final String USER_PWD = "userPassword"; @Inject Logger logger; - + @Inject EncryptionService encryptionService; - + @Inject MgtUtil mgtUtil; @@ -56,7 +60,8 @@ public class UserResource extends BaseResource { @GET @ProtectedApi(scopes = { ApiAccessConstants.USER_READ_ACCESS }) - public Response getUsers(@DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + public Response getUsers( + @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, @QueryParam(value = ApiConstants.SORT_BY) String sortBy, @@ -68,12 +73,12 @@ public Response getUsers(@DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryPar escapeLog(sortOrder)); } SearchRequest searchReq = createSearchRequest(userSrv.getPeopleBaseDn(), pattern, sortBy, sortOrder, startIndex, - limit, null, userSrv.getUserExclusionAttributesAsString(),mgtUtil.getRecordMaxCount()); + limit, null, userSrv.getUserExclusionAttributesAsString(), mgtUtil.getRecordMaxCount()); - List users = this.doSearch(searchReq); - logger.debug("User search result:{}", users); + List customUsers = this.doSearch(searchReq); + logger.debug("CustomUser search result:{}", customUsers); - return Response.ok(getUsers(users)).build(); + return Response.ok(customUsers).build(); } @GET @@ -91,17 +96,29 @@ public Response getUserByInum(@PathParam(ApiConstants.INUM) @NotNull String inum // excludedAttributes user = excludeUserAttributes(user); - return Response.ok(decryptUserPassword(user)).build(); + // decryptUserPassword + decryptUserPassword(user); + logger.debug("user:{}", user); + + // get custom user + CustomUser customUser = getCustomUser(user); + logger.debug("customUser:{}", customUser); + + return Response.ok(decryptUserPassword(customUser)).build(); } -/* + @POST @ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS }) - public Response createUser(@Valid User user) + public Response createUser(@Valid CustomUser customUser) throws EncryptionException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { - logger.debug("User details to be added - user:{}", escapeLog(user)); + logger.debug("User details to be added - customUser:{}", escapeLog(customUser)); } + // get User object + User user = setUserAttributes(customUser); + logger.debug("Create user:{}", user); + // checking mandatory attributes checkMissingAttributes(user); @@ -111,35 +128,47 @@ public Response createUser(@Valid User user) // excludedAttributes user = excludeUserAttributes(user); - return Response.status(Response.Status.CREATED).entity(user).build(); + // get custom user + customUser = getCustomUser(user); + logger.debug("newly created customUser:{}", customUser); + + return Response.status(Response.Status.CREATED).entity(customUser).build(); } @PUT @ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS }) - public Response updateUser(@Valid User user) + public Response updateUser(@Valid CustomUser customUser) throws EncryptionException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { - logger.debug("User details to be updated - user:{}", escapeLog(user)); + logger.debug("User details to be updated - customUser:{}", escapeLog(customUser)); } + // get User object + User user = setUserAttributes(customUser); + logger.debug("Create user:{}", user); + // checking mandatory attributes checkMissingAttributes(user); - + user = userSrv.updateUser(encryptUserPassword(user)); logger.debug("Updated user:{}", user); // excludedAttributes user = excludeUserAttributes(user); - return Response.ok(user).build(); + // get custom user + customUser = getCustomUser(user); + logger.debug("updated customUser:{}", customUser); + + return Response.ok(customUser).build(); } @PATCH @ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) public Response patchUser(@PathParam(ApiConstants.INUM) @NotNull String inum, - @NotNull UserPatchRequest userPatchRequest) - throws EncryptionException, IllegalAccessException, InvocationTargetException, JsonPatchException, IOException { + @NotNull UserPatchRequest userPatchRequest) throws EncryptionException, IllegalAccessException, + InvocationTargetException, JsonPatchException, IOException { if (logger.isDebugEnabled()) { logger.debug("User:{} to be patched with :{} ", escapeLog(inum), escapeLog(userPatchRequest)); } @@ -154,7 +183,11 @@ public Response patchUser(@PathParam(ApiConstants.INUM) @NotNull String inum, // excludedAttributes existingUser = excludeUserAttributes(existingUser); - return Response.ok(decryptUserPassword(existingUser)).build(); + // get custom user + CustomUser customUser = getCustomUser(existingUser); + logger.debug("patched customUser:{}", customUser); + + return Response.ok(decryptUserPassword(customUser)).build(); } @DELETE @@ -170,9 +203,8 @@ public Response deleteUser(@PathParam(ApiConstants.INUM) @NotNull String inum) { return Response.noContent().build(); } - */ - - private List doSearch(SearchRequest searchReq) throws IllegalAccessException, InvocationTargetException { + private List doSearch(SearchRequest searchReq) + throws EncryptionException, IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { logger.debug("User search params - searchReq:{} ", escapeLog(searchReq)); } @@ -194,7 +226,12 @@ private List doSearch(SearchRequest searchReq) throws IllegalAccessExcepti // excludedAttributes users = userSrv.excludeAttributes(users, searchReq.getExcludedAttributesStr()); - return users; + // decryptUserPassword + getUsers(users); + logger.debug("Users fetched - users:{}", users); + + // get customUser() + return getCustomUserList(users); } private User excludeUserAttributes(User user) throws IllegalAccessException, InvocationTargetException { @@ -212,7 +249,7 @@ private void checkMissingAttributes(User user) throwMissingAttributeError(missingAttributes); } - + private List getUsers(List users) throws EncryptionException { if (users != null && !users.isEmpty()) { for (User user : users) { @@ -223,7 +260,7 @@ private List getUsers(List users) throws EncryptionException { } return users; } - + private User encryptUserPassword(User user) throws EncryptionException { if (StringHelper.isNotEmpty(user.getAttribute(USER_PWD))) { user.setAttribute(USER_PWD, encryptionService.encrypt(user.getAttribute(USER_PWD)), false); @@ -232,11 +269,88 @@ private User encryptUserPassword(User user) throws EncryptionException { } private User decryptUserPassword(User user) throws EncryptionException { - if (StringHelper .isNotEmpty(user.getAttribute(USER_PWD))) { + if (StringHelper.isNotEmpty(user.getAttribute(USER_PWD))) { user.setAttribute(USER_PWD, encryptionService.decrypt(user.getAttribute(USER_PWD)), false); } return user; } - - + + private List getCustomUserList(List users) { + List customUserList = new ArrayList<>(); + if (users == null || users.isEmpty()) { + return customUserList; + } + + for (User user : users) { + CustomUser customUser = new CustomUser(); + setParentAttributes(customUser, user); + customUserList.add(customUser); + } + logger.debug("Custom Users - customUserList:{}", customUserList); + return customUserList; + } + + private CustomUser getCustomUser(User user) { + CustomUser customUser = new CustomUser(); + if (user == null) { + return customUser; + } + setParentAttributes(customUser, user); + logger.debug("Custom User - customUser:{}", customUser); + return customUser; + } + + public CustomUser setParentAttributes(CustomUser customUser, User user) { + customUser.setBaseDn(user.getBaseDn()); + customUser.setCreatedAt(user.getCreatedAt()); + customUser.setCustomAttributes(user.getCustomAttributes()); + customUser.setCustomObjectClasses(user.getCustomObjectClasses()); + customUser.setDn(user.getDn()); + customUser.setOxAuthPersistentJwt(user.getOxAuthPersistentJwt()); + customUser.setUpdatedAt(user.getUpdatedAt()); + customUser.setUserId(user.getUserId()); + + return setCustomUserAttributes(customUser, user); + } + + public CustomUser setCustomUserAttributes(CustomUser customUser, User user) { + customUser.setMail(user.getAttribute(MAIL)); + customUser.setDisplayName(user.getAttribute(DISPLAY_NAME)); + customUser.setJansStatus(user.getAttribute(JANS_STATUS)); + customUser.setGivenName(user.getAttribute(GIVEN_NAME)); + customUser.setUserPassword(user.getAttribute(USER_PWD)); + + customUser.removeAttribute(MAIL); + customUser.removeAttribute(DISPLAY_NAME); + customUser.removeAttribute(JANS_STATUS); + customUser.removeAttribute(GIVEN_NAME); + customUser.removeAttribute(USER_PWD); + + return customUser; + } + + private User setUserAttributes(CustomUser customUser) { + User user = new User(); + user.setBaseDn(customUser.getBaseDn()); + user.setCreatedAt(customUser.getCreatedAt()); + user.setCustomAttributes(customUser.getCustomAttributes()); + user.setCustomObjectClasses(customUser.getCustomObjectClasses()); + user.setDn(customUser.getDn()); + user.setOxAuthPersistentJwt(customUser.getOxAuthPersistentJwt()); + user.setUpdatedAt(customUser.getUpdatedAt()); + user.setUserId(customUser.getUserId()); + return setUserCustomAttributes(customUser, user); + } + + private User setUserCustomAttributes(CustomUser customUser, User user) { + user.setAttribute(MAIL, customUser.getMail(), false); + user.setAttribute(DISPLAY_NAME, customUser.getDisplayName(), false); + user.setAttribute(JANS_STATUS, customUser.getJansStatus(), false); + user.setAttribute(GIVEN_NAME, customUser.getGivenName(), false); + user.setAttribute(USER_PWD, customUser.getUserPassword(), false); + + logger.debug("Custom User - user:{}", user); + return user; + } + } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java index 7ebaf2b77ba..9fba435288a 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserService.java @@ -1,19 +1,17 @@ package io.jans.configapi.plugin.mgt.service; import com.github.fge.jsonpatch.JsonPatchException; -import io.jans.configapi.plugin.mgt.model.user.User; +import io.jans.as.common.model.common.User; import io.jans.as.common.util.AttributeConstants; import io.jans.as.model.config.StaticConfiguration; import io.jans.as.model.configuration.AppConfiguration; import io.jans.configapi.core.util.Jackson; import io.jans.configapi.plugin.mgt.model.user.UserPatchRequest; import io.jans.configapi.core.model.SearchRequest; -import io.jans.configapi.core.util.DataUtil; import io.jans.configapi.util.AuthUtil; import io.jans.orm.model.PagedResult; import io.jans.orm.model.SortOrder; import io.jans.orm.model.base.CustomObjectAttribute; -import io.jans.orm.reflect.property.Setter; import io.jans.orm.search.filter.Filter; import io.jans.util.StringHelper; @@ -80,27 +78,12 @@ public PagedResult searchUsers(SearchRequest searchRequest) { searchRequest.getStartIndex() - 1, searchRequest.getCount(), searchRequest.getMaxCount()); } - - public User getUserBasedOnInum(String inum) { - User result = null; - try { - io.jans.as.common.model.common.User user = getUserByInum(inum); - result = getConfigUser(user); - } catch (Exception ex) { - logger.error("Failed to load user entry", ex); - } - return result; - } - - private User getConfigUser(io.jans.as.common.model.common.User user) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return populateConfigUser(user); - } public void removeUser(User user) { persistenceEntryManager.removeRecursively(user.getDn(), User.class); } - public io.jans.as.common.model.common.User patchUser(String inum, UserPatchRequest userPatchRequest) throws JsonPatchException, IOException { + public User patchUser(String inum, UserPatchRequest userPatchRequest) throws JsonPatchException, IOException { if (logger.isDebugEnabled()) { logger.debug("Details to patch user inum:{}, UserPatchRequest:{} ", escapeLog(inum), escapeLog(userPatchRequest)); @@ -109,7 +92,7 @@ public io.jans.as.common.model.common.User patchUser(String inum, UserPatchReque return null; } - io.jans.as.common.model.common.User user = getUserByInum(inum); + User user = getUserByInum(inum); if (user == null) { return null; } @@ -136,9 +119,17 @@ public io.jans.as.common.model.common.User patchUser(String inum, UserPatchReque } - + public User getUserBasedOnInum(String inum) { + User result = null; + try { + result = getUserByInum(inum); + } catch (Exception ex) { + logger.error("Failed to load user entry", ex); + } + return result; + } - private io.jans.as.common.model.common.User updateCustomAttributes(io.jans.as.common.model.common.User user, List customAttributes) { + private User updateCustomAttributes(User user, List customAttributes) { logger.debug("Custom Attributes to update for - user:{}, customAttributes:{} ", user, customAttributes); if (customAttributes == null || customAttributes.isEmpty()) { @@ -230,7 +221,6 @@ public String getUserExclusionAttributesAsString() { return authUtil.getUserExclusionAttributesAsString(); } - public String checkMandatoryFields(User user) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { List mandatoryAttributes = authUtil.getUserMandatoryAttributes(); @@ -272,43 +262,4 @@ public String checkMandatoryFields(User user) return missingAttributes.toString(); } - private User populateConfigUser(io.jans.as.common.model.common.User user) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException - { - List mandatoryAttributes = authUtil.getUserMandatoryAttributes(); - logger.debug("mandatoryAttributess :{} ", mandatoryAttributes); - - User userConfig = (User) user; - StringBuilder missingAttributes = new StringBuilder(); - if (mandatoryAttributes == null || mandatoryAttributes.isEmpty()) { - return userConfig; - } - - List allFields = authUtil.getAllFields(user.getClass()); - logger.debug("All user fields :{} ", allFields); - - Object attributeValue = null; - for (String attribute : mandatoryAttributes) { - logger.debug("User class allFields:{} conatins attribute:{} ? :{} ", allFields, attribute, - authUtil.containsField(allFields, attribute)); - if (authUtil.containsField(allFields, attribute)) { - logger.debug("Checking if attribute:{} is simple attribute", attribute); - attributeValue = BeanUtils.getProperty(user, attribute); - logger.debug("User basic attribute:{} - attributeValue:{} ", attribute, attributeValue); - } else { - logger.debug("Checking if attribute:{} is custom attribute", attribute); - attributeValue = user.getAttribute(attribute); - logger.debug("User custom attribute:{} - attributeValue:{} ", attribute, attributeValue); - } - - //set attribute - Setter setterMethod = DataUtil.getSetterMethod(userConfig.getClass(), attribute); - Object propertyValue = setterMethod.getMethod().invoke(userConfig, attributeValue); - logger.error("After setterMethod invoked attribute:{}, propertyValue:{} ", attribute, propertyValue); - }//for - logger.debug("Checking mandatory userConfig:{} ", userConfig); - - logger.debug("Returning missingAttributes:{} ", missingAttributes); - - return userConfig; - } } From 3c3df7a1beee57fb851a4c820fcbbffb8418bd78 Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Tue, 17 May 2022 22:19:13 +0530 Subject: [PATCH 3/3] feat(jans-config-api): exposed attributes at root value --- .../io/jans/configapi/core/util/DataUtil.java | 176 ------------------ 1 file changed, 176 deletions(-) delete mode 100644 jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java deleted file mode 100644 index db1491e46e0..00000000000 --- a/jans-config-api/shared/src/main/java/io/jans/configapi/core/util/DataUtil.java +++ /dev/null @@ -1,176 +0,0 @@ -package io.jans.configapi.core.util; - -import io.jans.as.model.json.JsonApplier; -import io.jans.orm.exception.MappingException; -import io.jans.orm.reflect.property.Getter; -import io.jans.orm.reflect.property.Setter; -import io.jans.orm.reflect.util.ReflectHelper; - -import jakarta.enterprise.context.ApplicationScoped; -import java.beans.Introspector; -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -public class DataUtil { - - private DataUtil() { - } - - private static final Logger logger = LoggerFactory.getLogger(DataUtil.class); - - public static Class getPropertType(String className, String name) throws MappingException { - logger.error("className:{} , name:{} ", className, name); - return ReflectHelper.reflectedPropertyClass(className, name); - - } - - public static Getter getGetterMethod(Class clazz, String name) throws MappingException { - logger.error("Get Getter fromclazz:{} , name:{} ", clazz, name); - return ReflectHelper.getGetter(clazz, name); - } - - public static Setter getSetterMethod(Class clazz, String name) throws MappingException { - logger.error("Get Setter from clazz:{} for name:{} ", clazz, name); - return ReflectHelper.getSetter(clazz, name); - } - - public static Object getValue(Object object, String property) throws MappingException { - logger.error("Get value from object:{} for property:{} ", object, property); - return ReflectHelper.getValue(object, property); - } - - public static Method getSetter(String fieldName, Class clazz) throws Exception { - PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); - for (PropertyDescriptor p : props) - if (p.getName().equals(fieldName)) - return p.getWriteMethod(); - return null; - } - - public Object invokeReflectionGetter(Object obj, String variableName) { - try { - PropertyDescriptor pd = new PropertyDescriptor(variableName, obj.getClass()); - Method getter = pd.getReadMethod(); - if (getter != null) { - return getter.invoke(obj); - } else { - logger.error(String.format("Getter Method not found for class: %s property: %s", - obj.getClass().getName(), variableName)); - } - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException - | IntrospectionException e) { - logger.error(String.format("Getter Method ERROR for class: %s property: %s", obj.getClass().getName(), - variableName), e); - } - return null; - } - - public static void invokeReflectionSetter(Object obj, String propertyName, Object variableValue) { - PropertyDescriptor pd; - try { - pd = new PropertyDescriptor(propertyName, obj.getClass()); - Method method = pd.getWriteMethod(); - if (method != null) { - method.invoke(obj, variableValue); - } else { - logger.error(String.format(" Setter Method not found for class: %s property: %s", - obj.getClass().getName(), propertyName)); - } - } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { - logger.error(String.format("\n\n Setter Method invocation ERROR for class: %s property: %s", - obj.getClass().getName(), propertyName), e); - } - } - - public static boolean containsField(List allFields, String attribute) { - logger.error("allFields:{}, attribute:{}, allFields.contains(attribute):{} ", allFields, attribute, - allFields.stream().anyMatch(f -> f.getName().equals(attribute))); - - return allFields.stream().anyMatch(f -> f.getName().equals(attribute)); - } - - public static List getAllFields(Class type) { - List allFields = new ArrayList<>(); - allFields = getAllFields(allFields, type); - logger.error("Fields:{} of type:{} ", allFields, type); - - return allFields; - } - - public static List getAllFields(List fields, Class type) { - logger.error("Getting fields type:{} - fields:{} ", type, fields); - fields.addAll(Arrays.asList(type.getDeclaredFields())); - - if (type.getSuperclass() != null) { - getAllFields(fields, type.getSuperclass()); - } - logger.error("Final fields:{} of type:{} ", fields, type); - return fields; - } - - public static Map getFieldTypeMap(Class clazz) { - logger.error("clazz:{} ", clazz); - Map propertyTypeMap = new HashMap<>(); - - if (clazz == null) { - return propertyTypeMap; - } - - List fields = getAllFields(clazz); - logger.error("fields:{} ", fields); - - for (Field field : fields) { - logger.error( - "field:{} , field.getAnnotatedType():{}, field.getAnnotations():{} , field.getType().getAnnotations():{}, field.getType().getCanonicalName():{} , field.getType().getClass():{} , field.getType().getClasses():{} , field.getType().getComponentType():{}", - field, field.getAnnotatedType(), field.getAnnotations(), field.getType().getAnnotations(), - field.getType().getCanonicalName(), field.getType().getClass(), field.getType().getClasses(), - field.getType().getComponentType()); - propertyTypeMap.put(field.getName(), field.getType().getSimpleName()); - } - logger.error("Final propertyTypeMap{} ", propertyTypeMap); - return propertyTypeMap; - } - - public static Map getPropertyTypeMap(Class clazz) { - logger.error("clazz:{} for getting property and field map ", clazz); - Map propertyTypeMap = new HashMap<>(); - if (clazz == null) { - return propertyTypeMap; - } - logger.error("clazz.getCanonicalName():{}, clazz.getName():{}, clazz.getPackageName():{} ", - clazz.getCanonicalName(), clazz.getName(), clazz.getPackageName()); - String className = clazz.getName(); - List fields = getAllFields(clazz); - logger.error("fields:{} ", fields); - if (fields == null) { - return propertyTypeMap; - } - for (Field field : fields) { - logger.error("field:{} ", field); - Class dataTypeClass = getPropertType(className, field.getName()); - logger.error("dataTypeClass:{} ", dataTypeClass); - propertyTypeMap.put(field, dataTypeClass); - } - - logger.error("Final propertyTypeMap{} ", propertyTypeMap); - return propertyTypeMap; - } - - public static Object invokeGetterMethod(Object obj, String variableName) { - return JsonApplier.getInstance().invokeReflectionGetter(obj, variableName); - } - -}