in ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java [792:992]
public Pair<UserUR, StatusR> toUserUpdate(
final UserTO before,
final Collection<String> resources,
final SCIMPatchOperation op) {
StatusR statusR = null;
if (op.getPath() == null && op.getOp() != PatchOp.remove
&& !CollectionUtils.isEmpty(op.getValue())
&& op.getValue().getFirst() instanceof final SCIMUser after) {
if (after.getActive() != null && before.isSuspended() == after.isActive()) {
statusR = new StatusR.Builder(
before.getKey(),
after.isActive() ? StatusRType.REACTIVATE : StatusRType.SUSPEND).
resources(resources).
build();
}
UserTO updated = toUserTO(after, false);
updated.setKey(before.getKey());
return Pair.of(AnyOperations.diff(updated, before, true), statusR);
}
UserUR userUR = new UserUR.Builder(before.getKey()).build();
SCIMConf conf = confManager.get();
if (conf == null) {
return Pair.of(userUR, statusR);
}
switch (op.getPath().getAttribute()) {
case "externalId" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getExternalId(), op);
case "userName" -> {
if (op.getOp() != PatchOp.remove && !CollectionUtils.isEmpty(op.getValue())) {
userUR.setUsername(
new StringReplacePatchItem.Builder().value(op.getValue().getFirst().toString()).build());
}
}
case "password" -> {
if (op.getOp() != PatchOp.remove && !CollectionUtils.isEmpty(op.getValue())) {
userUR.setPassword(new PasswordPatch.Builder().value(op.getValue().getFirst().toString()).resources(
resources).build());
}
}
case "active" -> {
if (!CollectionUtils.isEmpty(op.getValue())) {
// Workaround for Microsoft Entra being not SCIM compliant on PATCH requests
if (op.getValue().getFirst() instanceof String a) {
op.setValue(List.of(BooleanUtils.toBoolean(a)));
}
statusR = new StatusR.Builder(before.getKey(),
(boolean) op.getValue().getFirst()
? StatusRType.REACTIVATE
: StatusRType.SUSPEND).resources(resources).build();
}
}
case "name" -> {
if (conf.getUserConf().getName() != null) {
if (op.getPath().getSub() == null || "familyName".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getFamilyName(), op);
}
if (op.getPath().getSub() == null || "formatted".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getFormatted(), op);
}
if (op.getPath().getSub() == null || "givenName".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getGivenName(), op);
}
if (op.getPath().getSub() == null || "honorificPrefix".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getHonorificPrefix(), op);
}
if (op.getPath().getSub() == null || "honorificSuffix".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getHonorificSuffix(), op);
}
if (op.getPath().getSub() == null || "middleName".equals(op.getPath().getSub())) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getName().getMiddleName(), op);
}
}
}
case "displayName" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getDisplayName(), op);
case "nickName" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getNickName(), op);
case "profileUrl" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getProfileUrl(), op);
case "title" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getTitle(), op);
case "userType" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getUserType(), op);
case "preferredLanguage" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getPreferredLanguage(), op);
case "locale" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getLocale(), op);
case "timezone" ->
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getTimezone(), op);
case "emails" -> {
if (!CollectionUtils.isEmpty(op.getValue()) && op.getValue().getFirst() instanceof SCIMUser) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getEmails(),
((SCIMUser) op.getValue().getFirst()).getEmails(), op.getOp());
} else if (op.getPath().getFilter() != null) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getEmails(), op);
}
}
case "phoneNumbers" -> {
if (!CollectionUtils.isEmpty(op.getValue()) && op.getValue().getFirst() instanceof SCIMUser) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getPhoneNumbers(),
((SCIMUser) op.getValue().getFirst()).getPhoneNumbers(), op.getOp());
} else if (op.getPath().getFilter() != null) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getPhoneNumbers(), op);
}
}
case "ims" -> {
if (!CollectionUtils.isEmpty(op.getValue()) && op.getValue().getFirst() instanceof SCIMUser) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getIms(),
((SCIMUser) op.getValue().getFirst()).getIms(), op.getOp());
} else if (op.getPath().getFilter() != null) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getIms(), op);
}
}
case "photos" -> {
if (!CollectionUtils.isEmpty(op.getValue()) && op.getValue().getFirst() instanceof SCIMUser) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getPhotos(),
((SCIMUser) op.getValue().getFirst()).getPhotos(), op.getOp());
} else if (op.getPath().getFilter() != null) {
setAttribute(userUR.getPlainAttrs(), conf.getUserConf().getPhotos(), op);
}
}
case "addresses" -> {
if (!CollectionUtils.isEmpty(op.getValue())
&& op.getValue().getFirst() instanceof final SCIMUser after) {
after.getAddresses().stream().filter(address -> address.getType() != null).forEach(
address -> conf.getUserConf().getAddresses().stream()
.filter(object -> address.getType().equals(object.getType().name())).findFirst()
.ifPresent(addressConf -> setAttribute(userUR.getPlainAttrs(), addressConf, op)));
} else if (op.getPath().getFilter() != null) {
conf.getUserConf().getAddresses().stream().filter(addressConf -> BooleanUtils.toBoolean(
JexlUtils.evaluateExpr(filter2JexlExpression(op.getPath().getFilter()),
new MapContext(Map.of("type", addressConf.getType().name()))).toString()))
.findFirst()
.ifPresent(addressConf -> setAttribute(userUR.getPlainAttrs(), addressConf, op));
}
}
case "employeeNumber" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getEmployeeNumber).orElse(null), op);
case "costCenter" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getCostCenter).orElse(null), op);
case "organization" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getOrganization).orElse(null), op);
case "division" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getDivision).orElse(null), op);
case "department" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getDepartment).orElse(null), op);
case "manager" ->
setAttribute(userUR.getPlainAttrs(),
Optional.ofNullable(conf.getEnterpriseUserConf()).
map(SCIMEnterpriseUserConf::getManager).map(SCIMManagerConf::getKey).orElse(null), op);
default -> {
Optional.ofNullable(conf.getExtensionUserConf()).
flatMap(schema -> Optional.ofNullable(schema.asMap().get(op.getPath().getAttribute()))).
ifPresent(schema -> setAttribute(userUR.getPlainAttrs(), schema, op));
}
}
return Pair.of(userUR, statusR);
}