use of org.apache.syncope.client.enduser.model.CustomAttributesInfo in project syncope by apache.
the class UserSelfUpdateResource method newResourceResponse.
@Override
protected ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
ResourceResponse response = new AbstractResource.ResourceResponse();
response.setContentType(MediaType.TEXT_PLAIN);
try {
HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
if (!xsrfCheck(request)) {
LOG.error("XSRF TOKEN does not match");
response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
return response;
}
if (!captchaCheck(request.getHeader("captcha"), request.getSession().getAttribute(SyncopeEnduserConstants.CAPTCHA_SESSION_KEY))) {
throw new IllegalArgumentException("Entered captcha is not matching");
}
UserTO userTO = MAPPER.readValue(request.getReader().readLine(), UserTO.class);
Map<String, CustomAttributesInfo> customForm = SyncopeEnduserApplication.get().getCustomForm();
// check if request is compliant with customization form rules
if (UserRequestValidator.compliant(userTO, customForm, false)) {
// 1. membership attributes management
Set<AttrTO> membAttrs = new HashSet<>();
userTO.getPlainAttrs().stream().filter(attr -> (attr.getSchema().contains(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR))).forEachOrdered((attr) -> {
String[] simpleAttrs = attr.getSchema().split(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR);
MembershipTO membership = userTO.getMemberships().stream().filter(item -> simpleAttrs[0].equals(item.getGroupName())).findFirst().orElse(null);
if (membership == null) {
membership = new MembershipTO.Builder().group(null, simpleAttrs[0]).build();
userTO.getMemberships().add(membership);
}
AttrTO clone = SerializationUtils.clone(attr);
clone.setSchema(simpleAttrs[1]);
membership.getPlainAttrs().add(clone);
membAttrs.add(attr);
});
userTO.getPlainAttrs().removeAll(membAttrs);
// 2. millis -> Date conversion for PLAIN attributes of USER and its MEMBERSHIPS
SyncopeEnduserSession.get().getDatePlainSchemas().stream().map(plainSchema -> {
millisToDate(userTO.getPlainAttrs(), plainSchema);
return plainSchema;
}).forEachOrdered(plainSchema -> {
userTO.getMemberships().forEach(membership -> {
millisToDate(membership.getPlainAttrs(), plainSchema);
});
});
membAttrs.clear();
userTO.getDerAttrs().stream().filter(attr -> (attr.getSchema().contains(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR))).forEachOrdered(attr -> {
String[] simpleAttrs = attr.getSchema().split(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR);
MembershipTO membership = userTO.getMemberships().stream().filter(item -> simpleAttrs[0].equals(item.getGroupName())).findFirst().orElse(null);
if (membership == null) {
membership = new MembershipTO.Builder().group(null, simpleAttrs[0]).build();
userTO.getMemberships().add(membership);
}
AttrTO clone = SerializationUtils.clone(attr);
clone.setSchema(simpleAttrs[1]);
membership.getDerAttrs().add(clone);
membAttrs.add(attr);
});
userTO.getDerAttrs().removeAll(membAttrs);
membAttrs.clear();
userTO.getVirAttrs().stream().filter(attr -> (attr.getSchema().contains(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR))).forEachOrdered((attr) -> {
String[] simpleAttrs = attr.getSchema().split(SyncopeEnduserConstants.MEMBERSHIP_ATTR_SEPARATOR);
MembershipTO membership = userTO.getMemberships().stream().filter(item -> simpleAttrs[0].equals(item.getGroupName())).findFirst().orElse(null);
if (membership == null) {
membership = new MembershipTO.Builder().group(null, simpleAttrs[0]).build();
userTO.getMemberships().add(membership);
}
AttrTO clone = SerializationUtils.clone(attr);
clone.setSchema(simpleAttrs[1]);
membership.getVirAttrs().add(clone);
membAttrs.add(attr);
});
userTO.getVirAttrs().removeAll(membAttrs);
// get old user object from session
UserTO selfTO = SyncopeEnduserSession.get().getSelfTO();
// align "userTO" and "selfTO" objects
if (customForm != null && !customForm.isEmpty()) {
completeUserObject(userTO, selfTO);
}
// create diff patch
UserPatch userPatch = AnyOperations.diff(userTO, selfTO, false);
// update user by patch
Response res = SyncopeEnduserSession.get().getService(userTO.getETagValue(), UserSelfService.class).update(userPatch);
buildResponse(response, res.getStatus(), res.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL) ? "User [" + userTO.getUsername() + "] successfully updated" : "ErrorMessage{{ " + res.getStatusInfo().getReasonPhrase() + " }}");
} else {
LOG.warn("Incoming update request [{}] is not compliant with form customization rules." + " Update NOT allowed", userTO.getUsername());
buildResponse(response, Response.Status.OK.getStatusCode(), "User: " + userTO.getUsername() + " successfully created");
}
} catch (final Exception e) {
LOG.error("Error while updating user", e);
response.setError(Response.Status.BAD_REQUEST.getStatusCode(), new StringBuilder().append("ErrorMessage{{ ").append(e.getMessage()).append(" }}").toString());
}
return response;
}
use of org.apache.syncope.client.enduser.model.CustomAttributesInfo in project syncope by apache.
the class UserRequestValidatorTest method testCompliant.
@Test
public void testCompliant() throws IOException {
UserTO userTO = new UserTO();
// plain
AttrTO firstname = attrTO("firstname", "defaultFirstname");
AttrTO surname = attrTO("surname", "surnameValue");
AttrTO additionalCtype = attrTO("additional#ctype", "ctypeValue");
AttrTO notAllowed = attrTO("not_allowed", "notAllowedValue");
userTO.getPlainAttrs().addAll(Arrays.asList(firstname, surname, notAllowed, additionalCtype));
Map<String, CustomAttributesInfo> customForm = new ObjectMapper().readValue(new ClassPathResource("customForm.json").getFile(), new TypeReference<HashMap<String, CustomAttributesInfo>>() {
});
// not allowed because of presence of notAllowed attribute
assertFalse(UserRequestValidator.compliant(userTO, customForm, true));
// remove notAllowed attribute and make it compliant
userTO.getPlainAttrs().remove(notAllowed);
assertTrue(UserRequestValidator.compliant(userTO, customForm, true));
// firstname must have only one defaultValue
userTO.getPlainAttr("firstname").get().getValues().add("notAllowedFirstnameValue");
assertFalse(UserRequestValidator.compliant(userTO, customForm, true));
assertTrue(UserRequestValidator.compliant(userTO, customForm, false));
// clean
userTO.getPlainAttr("firstname").get().getValues().remove("notAllowedFirstnameValue");
// derived must not be present
AttrTO derivedNotAllowed = attrTO("derivedNotAllowed");
userTO.getDerAttrs().add(derivedNotAllowed);
assertFalse(UserRequestValidator.compliant(userTO, customForm, true));
// clean
userTO.getDerAttrs().clear();
// virtual
AttrTO virtualdata = attrTO("virtualdata", "defaultVirtualData");
userTO.getVirAttrs().add(virtualdata);
assertTrue(UserRequestValidator.compliant(userTO, customForm, true));
// with empty form is compliant by definition
assertTrue(UserRequestValidator.compliant(userTO, new HashMap<>(), true));
}
use of org.apache.syncope.client.enduser.model.CustomAttributesInfo in project syncope by apache.
the class SchemaResource method newResourceResponse.
@Override
protected AbstractResource.ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
LOG.debug("Search all {} any type kind related schemas", AnyTypeKind.USER.name());
ResourceResponse response = new AbstractResource.ResourceResponse();
response.setContentType(MediaType.APPLICATION_JSON);
try {
HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
if (!xsrfCheck(request)) {
LOG.error("XSRF TOKEN does not match");
response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
return response;
}
List<String> classes = Collections.emptyList();
String group = attributes.getParameters().get("group").toString();
if (group != null) {
try {
TypeExtensionTO typeExt = SyncopeEnduserSession.get().getService(SyncopeService.class).readUserTypeExtension(group);
classes = typeExt.getAuxClasses();
} catch (Exception e) {
LOG.error("Could not read User type extension for Group {}", group);
}
} else {
String anyTypeClass = attributes.getParameters().get("anyTypeClass").toString();
if (anyTypeClass != null) {
classes = Collections.singletonList(anyTypeClass);
} else {
classes = SyncopeEnduserSession.get().getService(SyncopeService.class).platform().getUserClasses();
}
}
// USER from customization, if empty or null ignore it, use it to filter attributes otherwise
Map<String, CustomAttributesInfo> customForm = SyncopeEnduserApplication.get().getCustomForm();
SchemaService schemaService = SyncopeEnduserSession.get().getService(SchemaService.class);
final List<SchemaTO> plainSchemas = classes.isEmpty() ? Collections.<SchemaTO>emptyList() : customForm == null || customForm.isEmpty() || customForm.get(SchemaType.PLAIN.name()) == null ? schemaService.search(new SchemaQuery.Builder().type(SchemaType.PLAIN).anyTypeClasses(classes).build()) : customForm.get(SchemaType.PLAIN.name()).isShow() ? customizeSchemas(schemaService.search(new SchemaQuery.Builder().type(SchemaType.PLAIN).anyTypeClasses(classes).build()), group, customForm.get(SchemaType.PLAIN.name()).getAttributes()) : Collections.<SchemaTO>emptyList();
final List<SchemaTO> derSchemas = classes.isEmpty() ? Collections.<SchemaTO>emptyList() : customForm == null || customForm.isEmpty() || customForm.get(SchemaType.DERIVED.name()) == null ? schemaService.search(new SchemaQuery.Builder().type(SchemaType.DERIVED).anyTypeClasses(classes).build()) : customForm.get(SchemaType.DERIVED.name()).isShow() ? customizeSchemas(schemaService.search(new SchemaQuery.Builder().type(SchemaType.DERIVED).anyTypeClasses(classes).build()), group, customForm.get(SchemaType.DERIVED.name()).getAttributes()) : Collections.<SchemaTO>emptyList();
final List<SchemaTO> virSchemas = classes.isEmpty() ? Collections.<SchemaTO>emptyList() : customForm == null || customForm.isEmpty() || customForm.get(SchemaType.VIRTUAL.name()) == null ? schemaService.search(new SchemaQuery.Builder().type(SchemaType.VIRTUAL).anyTypeClasses(classes).build()) : customForm.get(SchemaType.VIRTUAL.name()).isShow() ? customizeSchemas(schemaService.search(new SchemaQuery.Builder().type(SchemaType.VIRTUAL).anyTypeClasses(classes).build()), group, customForm.get(SchemaType.VIRTUAL.name()).getAttributes()) : Collections.<SchemaTO>emptyList();
if (group != null) {
plainSchemas.forEach(schema -> {
schema.setKey(compositeSchemaKey(group, schema.getKey()));
});
derSchemas.forEach(schema -> {
schema.setKey(compositeSchemaKey(group, schema.getKey()));
});
virSchemas.forEach(schema -> {
schema.setKey(compositeSchemaKey(group, schema.getKey()));
});
}
response.setTextEncoding(StandardCharsets.UTF_8.name());
response.setWriteCallback(new AbstractResource.WriteCallback() {
@Override
public void writeData(final IResource.Attributes attributes) throws IOException {
attributes.getResponse().write(MAPPER.writeValueAsString(new SchemaResponse().plainSchemas(plainSchemas).derSchemas(derSchemas).virSchemas(virSchemas)));
}
});
response.setStatusCode(Response.Status.OK.getStatusCode());
} catch (Exception e) {
LOG.error("Error retrieving {} any type kind related schemas", AnyTypeKind.USER.name(), e);
response.setError(Response.Status.BAD_REQUEST.getStatusCode(), new StringBuilder().append("ErrorMessage{{ ").append(e.getMessage()).append(" }}").toString());
}
return response;
}
use of org.apache.syncope.client.enduser.model.CustomAttributesInfo in project syncope by apache.
the class SyncopeEnduserApplication method init.
@Override
protected void init() {
super.init();
// read enduser.properties
Properties props = PropertyUtils.read(getClass(), ENDUSER_PROPERTIES, "enduser.directory").getLeft();
domain = props.getProperty("domain", SyncopeConstants.MASTER_DOMAIN);
adminUser = props.getProperty("adminUser");
Args.notNull(adminUser, "<adminUser>");
anonymousUser = props.getProperty("anonymousUser");
Args.notNull(anonymousUser, "<anonymousUser>");
anonymousKey = props.getProperty("anonymousKey");
Args.notNull(anonymousKey, "<anonymousKey>");
captchaEnabled = Boolean.parseBoolean(props.getProperty("captcha"));
Args.notNull(captchaEnabled, "<captcha>");
xsrfEnabled = Boolean.parseBoolean(props.getProperty("xsrf"));
Args.notNull(xsrfEnabled, "<xsrf>");
String scheme = props.getProperty("scheme");
Args.notNull(scheme, "<scheme>");
String host = props.getProperty("host");
Args.notNull(host, "<host>");
String port = props.getProperty("port");
Args.notNull(port, "<port>");
String rootPath = props.getProperty("rootPath");
Args.notNull(rootPath, "<rootPath>");
String useGZIPCompression = props.getProperty("useGZIPCompression");
Args.notNull(useGZIPCompression, "<useGZIPCompression>");
maxUploadFileSizeMB = props.getProperty("maxUploadFileSizeMB") == null ? null : Integer.valueOf(props.getProperty("maxUploadFileSizeMB"));
clientFactory = new SyncopeClientFactoryBean().setAddress(scheme + "://" + host + ":" + port + "/" + rootPath).setContentType(SyncopeClientFactoryBean.ContentType.JSON).setUseCompression(BooleanUtils.toBoolean(useGZIPCompression));
// read customForm.json
try (InputStream is = getClass().getResourceAsStream("/" + CUSTOM_FORM_FILE)) {
customForm = MAPPER.readValue(is, new TypeReference<HashMap<String, CustomAttributesInfo>>() {
});
File enduserDir = new File(props.getProperty("enduser.directory"));
boolean existsEnduserDir = enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory();
if (existsEnduserDir) {
File customFormFile = FileUtils.getFile(enduserDir, CUSTOM_FORM_FILE);
if (customFormFile.exists() && customFormFile.canRead() && customFormFile.isFile()) {
customForm = MAPPER.readValue(FileUtils.openInputStream(customFormFile), new TypeReference<HashMap<String, CustomAttributesInfo>>() {
});
}
}
FileAlterationObserver observer = existsEnduserDir ? new FileAlterationObserver(enduserDir, pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_FILE)) : new FileAlterationObserver(getClass().getResource("/" + CUSTOM_FORM_FILE).getFile(), pathname -> StringUtils.contains(pathname.getPath(), CUSTOM_FORM_FILE));
FileAlterationMonitor monitor = new FileAlterationMonitor(5000);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
@Override
public void onFileChange(final File file) {
try {
LOG.trace("{} has changed. Reloading form customization configuration.", CUSTOM_FORM_FILE);
customForm = MAPPER.readValue(FileUtils.openInputStream(file), new TypeReference<HashMap<String, CustomAttributesInfo>>() {
});
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
@Override
public void onFileCreate(final File file) {
try {
LOG.trace("{} has been created. Loading form customization configuration.", CUSTOM_FORM_FILE);
customForm = MAPPER.readValue(FileUtils.openInputStream(file), new TypeReference<HashMap<String, CustomAttributesInfo>>() {
});
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
@Override
public void onFileDelete(final File file) {
LOG.trace("{} has been deleted. Resetting form customization configuration.", CUSTOM_FORM_FILE);
customForm = null;
}
};
observer.addListener(listener);
monitor.addObserver(observer);
monitor.start();
} catch (Exception e) {
throw new WicketRuntimeException("Could not read " + CUSTOM_FORM_FILE, e);
}
// mount resources
ClassPathScanImplementationLookup classPathScanImplementationLookup = (ClassPathScanImplementationLookup) getServletContext().getAttribute(EnduserInitializer.CLASSPATH_LOOKUP);
for (final Class<? extends AbstractResource> resource : classPathScanImplementationLookup.getResources()) {
Resource annotation = resource.getAnnotation(Resource.class);
if (annotation == null) {
LOG.debug("No @Resource annotation found on {}, ignoring", resource.getName());
} else {
try {
final AbstractResource instance = resource.newInstance();
mountResource(annotation.path(), new ResourceReference(annotation.key()) {
private static final long serialVersionUID = -128426276529456602L;
@Override
public IResource getResource() {
return instance;
}
});
} catch (Exception e) {
LOG.error("Could not instantiate {}", resource.getName(), e);
}
}
}
// mount captcha resource only if captcha is enabled
if (captchaEnabled) {
mountResource("/api/captcha", new ResourceReference("captcha") {
private static final long serialVersionUID = -128426276529456602L;
@Override
public IResource getResource() {
return new CaptchaResource();
}
});
}
}
Aggregations