use of org.apache.syncope.common.lib.patch.UserPatch 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.common.lib.patch.UserPatch in project syncope by apache.
the class AnyOperations method patch.
public static UserTO patch(final UserTO userTO, final UserPatch userPatch) {
UserTO result = SerializationUtils.clone(userTO);
patch(userTO, userPatch, result);
// 1. password
if (userPatch.getPassword() != null) {
result.setPassword(userPatch.getPassword().getValue());
}
// 2. username
if (userPatch.getUsername() != null) {
result.setUsername(userPatch.getUsername().getValue());
}
// 3. relationships
userPatch.getRelationships().forEach(relPatch -> {
if (relPatch.getRelationshipTO() == null) {
LOG.warn("Invalid {} specified: {}", RelationshipPatch.class.getName(), relPatch);
} else {
result.getRelationships().remove(relPatch.getRelationshipTO());
if (relPatch.getOperation() == PatchOperation.ADD_REPLACE) {
result.getRelationships().add(relPatch.getRelationshipTO());
}
}
});
// 4. memberships
userPatch.getMemberships().forEach(membPatch -> {
if (membPatch.getGroup() == null) {
LOG.warn("Invalid {} specified: {}", MembershipPatch.class.getName(), membPatch);
} else {
Optional<MembershipTO> memb = result.getMemberships().stream().filter(membership -> membPatch.getGroup().equals(membership.getGroupKey())).findFirst();
if (memb.isPresent()) {
result.getMemberships().remove(memb.get());
}
if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
MembershipTO newMembershipTO = new MembershipTO.Builder().group(membPatch.getGroup()).build();
// 3. plain attributes
newMembershipTO.getPlainAttrs().addAll(membPatch.getPlainAttrs());
// 4. virtual attributes
newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
result.getMemberships().add(newMembershipTO);
}
}
});
// 5. roles
for (StringPatchItem rolePatch : userPatch.getRoles()) {
switch(rolePatch.getOperation()) {
case ADD_REPLACE:
result.getRoles().add(rolePatch.getValue());
break;
case DELETE:
default:
result.getRoles().remove(rolePatch.getValue());
}
}
return result;
}
use of org.apache.syncope.common.lib.patch.UserPatch in project syncope by apache.
the class AnyOperations method diff.
/**
* Calculate modifications needed by first in order to be equal to second.
*
* @param updated updated UserTO
* @param original original UserTO
* @param incremental perform incremental diff (without removing existing info)
* @return UserPatch containing differences
*/
public static UserPatch diff(final UserTO updated, final UserTO original, final boolean incremental) {
UserPatch result = new UserPatch();
diff(updated, original, result, incremental);
// 1. password
if (updated.getPassword() != null && (original.getPassword() == null || !original.getPassword().equals(updated.getPassword()))) {
result.setPassword(new PasswordPatch.Builder().value(updated.getPassword()).resources(updated.getResources()).build());
}
// 2. username
result.setUsername(replacePatchItem(updated.getUsername(), original.getUsername(), new StringReplacePatchItem()));
// 3. security question / answer
if (updated.getSecurityQuestion() == null) {
result.setSecurityQuestion(null);
result.setSecurityAnswer(null);
} else if (!updated.getSecurityQuestion().equals(original.getSecurityQuestion()) || StringUtils.isNotBlank(updated.getSecurityAnswer())) {
result.setSecurityQuestion(new StringReplacePatchItem.Builder().value(updated.getSecurityQuestion()).build());
result.setSecurityAnswer(new StringReplacePatchItem.Builder().value(updated.getSecurityAnswer()).build());
}
result.setMustChangePassword(replacePatchItem(updated.isMustChangePassword(), original.isMustChangePassword(), new BooleanReplacePatchItem()));
// 4. roles
if (!incremental) {
original.getRoles().stream().filter(role -> !updated.getRoles().contains(role)).forEach(toRemove -> {
result.getRoles().add(new StringPatchItem.Builder().operation(PatchOperation.DELETE).value(toRemove).build());
});
}
updated.getRoles().stream().filter(role -> !original.getRoles().contains(role)).forEach(toAdd -> {
result.getRoles().add(new StringPatchItem.Builder().operation(PatchOperation.ADD_REPLACE).value(toAdd).build());
});
// 5. relationships
Map<Pair<String, String>, RelationshipTO> updatedRels = EntityTOUtils.buildRelationshipMap(updated.getRelationships());
Map<Pair<String, String>, RelationshipTO> originalRels = EntityTOUtils.buildRelationshipMap(original.getRelationships());
updatedRels.entrySet().stream().filter(entry -> (!originalRels.containsKey(entry.getKey()))).forEachOrdered(entry -> {
result.getRelationships().add(new RelationshipPatch.Builder().operation(PatchOperation.ADD_REPLACE).relationshipTO(entry.getValue()).build());
});
if (!incremental) {
originalRels.keySet().stream().filter(relationship -> !updatedRels.containsKey(relationship)).forEach(key -> {
result.getRelationships().add(new RelationshipPatch.Builder().operation(PatchOperation.DELETE).relationshipTO(originalRels.get(key)).build());
});
}
// 6. memberships
Map<String, MembershipTO> updatedMembs = EntityTOUtils.buildMembershipMap(updated.getMemberships());
Map<String, MembershipTO> originalMembs = EntityTOUtils.buildMembershipMap(original.getMemberships());
updatedMembs.entrySet().stream().map(entry -> {
MembershipPatch membershipPatch = new MembershipPatch.Builder().operation(PatchOperation.ADD_REPLACE).group(entry.getValue().getGroupKey()).build();
MembershipTO omemb;
if (originalMembs.containsKey(entry.getKey())) {
// get the original membership
omemb = originalMembs.get(entry.getKey());
} else {
// create an empty one to generate the patch
omemb = new MembershipTO.Builder().group(entry.getKey()).build();
}
diff(entry.getValue(), omemb, membershipPatch, incremental);
return membershipPatch;
}).forEachOrdered(membershipPatch -> {
result.getMemberships().add(membershipPatch);
});
if (!incremental) {
originalMembs.keySet().stream().filter(membership -> !updatedMembs.containsKey(membership)).forEach(key -> {
result.getMemberships().add(new MembershipPatch.Builder().operation(PatchOperation.DELETE).group(originalMembs.get(key).getGroupKey()).build());
});
}
return result;
}
use of org.apache.syncope.common.lib.patch.UserPatch in project syncope by apache.
the class FlowableUserWorkflowAdapter method doConfirmPasswordReset.
@Override
protected WorkflowResult<Pair<UserPatch, Boolean>> doConfirmPasswordReset(final User user, final String token, final String password) {
Map<String, Object> variables = new HashMap<>(4);
variables.put(TOKEN, token);
variables.put(PASSWORD, password);
variables.put(USER_TO, dataBinder.getUserTO(user, true));
variables.put(EVENT, "confirmPasswordReset");
Set<String> tasks = doExecuteTask(user, "confirmPasswordReset", variables);
userDAO.save(user);
PropagationByResource propByRes = engine.getRuntimeService().getVariable(user.getWorkflowId(), PROP_BY_RESOURCE, PropagationByResource.class);
UserPatch updatedPatch = engine.getRuntimeService().getVariable(user.getWorkflowId(), USER_PATCH, UserPatch.class);
Boolean propagateEnable = engine.getRuntimeService().getVariable(user.getWorkflowId(), PROPAGATE_ENABLE, Boolean.class);
return new WorkflowResult<>(Pair.of(updatedPatch, propagateEnable), propByRes, tasks);
}
use of org.apache.syncope.common.lib.patch.UserPatch in project syncope by apache.
the class Update method doExecute.
@Override
protected void doExecute(final String executionId) {
User user = engine.getRuntimeService().getVariable(executionId, FlowableUserWorkflowAdapter.USER, User.class);
UserPatch userPatch = engine.getRuntimeService().getVariable(executionId, FlowableUserWorkflowAdapter.USER_PATCH, UserPatch.class);
user = userDAO.save(user);
UserTO original = dataBinder.getUserTO(user, true);
PropagationByResource propByRes = dataBinder.update(user, userPatch);
PasswordPatch password = userPatch.getPassword();
Set<AttrTO> virAttrs = userPatch.getVirAttrs();
UserTO updated = dataBinder.getUserTO(user.getKey());
userPatch = AnyOperations.diff(updated, original, false);
userPatch.setPassword(password);
userPatch.getVirAttrs().clear();
userPatch.getVirAttrs().addAll(virAttrs);
// report updated user and propagation by resource as result
engine.getRuntimeService().setVariable(executionId, FlowableUserWorkflowAdapter.USER, user);
engine.getRuntimeService().setVariable(executionId, FlowableUserWorkflowAdapter.USER_TO, updated);
engine.getRuntimeService().setVariable(executionId, FlowableUserWorkflowAdapter.USER_PATCH, userPatch);
engine.getRuntimeService().setVariable(executionId, FlowableUserWorkflowAdapter.PROP_BY_RESOURCE, propByRes);
}
Aggregations