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); + } + +}