use of org.identityconnectors.framework.common.objects.Attribute in project syncope by apache.
the class MappingManagerImpl method prepareAttr.
/**
* Prepare an attribute to be sent to a connector instance.
*
* @param provision external resource
* @param mapItem mapping item for the given attribute
* @param any given any object
* @param password clear-text password
* @return connObjectKey + prepared attribute
*/
private Pair<String, Attribute> prepareAttr(final Provision provision, final Item mapItem, final Any<?> any, final String password) {
IntAttrName intAttrName;
try {
intAttrName = intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind());
} catch (ParseException e) {
LOG.error("Invalid intAttrName '{}' specified, ignoring", mapItem.getIntAttrName(), e);
return null;
}
boolean readOnlyVirSchema = false;
Schema schema = null;
AttrSchemaType schemaType = AttrSchemaType.String;
if (intAttrName.getSchemaType() != null) {
switch(intAttrName.getSchemaType()) {
case PLAIN:
schema = plainSchemaDAO.find(intAttrName.getSchemaName());
if (schema != null) {
schemaType = schema.getType();
}
break;
case VIRTUAL:
schema = virSchemaDAO.find(intAttrName.getSchemaName());
readOnlyVirSchema = (schema != null && schema.isReadonly());
break;
default:
}
}
List<PlainAttrValue> values = getIntValues(provision, mapItem, intAttrName, any);
LOG.debug("Define mapping for: " + "\n* ExtAttrName " + mapItem.getExtAttrName() + "\n* is connObjectKey " + mapItem.isConnObjectKey() + "\n* is password " + mapItem.isPassword() + "\n* mandatory condition " + mapItem.getMandatoryCondition() + "\n* Schema " + intAttrName.getSchemaName() + "\n* ClassType " + schemaType.getType().getName() + "\n* Values " + values);
Pair<String, Attribute> result;
if (readOnlyVirSchema) {
result = null;
} else {
List<Object> objValues = new ArrayList<>();
for (PlainAttrValue value : values) {
if (FrameworkUtil.isSupportedAttributeType(schemaType.getType())) {
objValues.add(value.getValue());
} else {
objValues.add(value.getValueAsString(schemaType));
}
}
if (mapItem.isConnObjectKey()) {
result = Pair.of(objValues.isEmpty() ? null : objValues.iterator().next().toString(), null);
} else if (mapItem.isPassword() && any instanceof User) {
String passwordAttrValue = password;
if (StringUtils.isBlank(passwordAttrValue)) {
User user = (User) any;
if (user.canDecodePassword()) {
try {
passwordAttrValue = ENCRYPTOR.decode(user.getPassword(), user.getCipherAlgorithm());
} catch (Exception e) {
LOG.error("Could not decode password for {}", user, e);
}
} else if (provision.getResource().isRandomPwdIfNotProvided()) {
try {
passwordAttrValue = passwordGenerator.generate(provision.getResource());
} catch (InvalidPasswordRuleConf e) {
LOG.error("Could not generate policy-compliant random password for {}", user, e);
}
}
}
if (passwordAttrValue == null) {
result = null;
} else {
result = Pair.of(null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
}
} else if (schema != null && schema.isMultivalue()) {
result = Pair.of(null, AttributeBuilder.build(mapItem.getExtAttrName(), objValues));
} else {
result = Pair.of(null, objValues.isEmpty() ? AttributeBuilder.build(mapItem.getExtAttrName()) : AttributeBuilder.build(mapItem.getExtAttrName(), objValues.iterator().next()));
}
}
return result;
}
use of org.identityconnectors.framework.common.objects.Attribute in project syncope by apache.
the class MappingManagerImpl method setIntValues.
@Transactional(readOnly = true)
@Override
public void setIntValues(final Item mapItem, final Attribute attr, final AnyTO anyTO, final AnyUtils anyUtils) {
List<Object> values = null;
if (attr != null) {
values = attr.getValue();
for (ItemTransformer transformer : MappingUtils.getItemTransformers(mapItem)) {
values = transformer.beforePull(mapItem, anyTO, values);
}
}
values = values == null ? Collections.emptyList() : values;
IntAttrName intAttrName;
try {
intAttrName = intAttrNameParser.parse(mapItem.getIntAttrName(), anyUtils.getAnyTypeKind());
} catch (ParseException e) {
LOG.error("Invalid intAttrName '{}' specified, ignoring", mapItem.getIntAttrName(), e);
return;
}
if (intAttrName.getField() != null) {
switch(intAttrName.getField()) {
case "password":
if (anyTO instanceof UserTO && !values.isEmpty()) {
((UserTO) anyTO).setPassword(ConnObjectUtils.getPassword(values.get(0)));
}
break;
case "username":
if (anyTO instanceof UserTO) {
((UserTO) anyTO).setUsername(values.isEmpty() || values.get(0) == null ? null : values.get(0).toString());
}
break;
case "name":
if (anyTO instanceof GroupTO) {
((GroupTO) anyTO).setName(values.isEmpty() || values.get(0) == null ? null : values.get(0).toString());
} else if (anyTO instanceof AnyObjectTO) {
((AnyObjectTO) anyTO).setName(values.isEmpty() || values.get(0) == null ? null : values.get(0).toString());
}
break;
case "mustChangePassword":
if (anyTO instanceof UserTO && !values.isEmpty() && values.get(0) != null) {
((UserTO) anyTO).setMustChangePassword(BooleanUtils.toBoolean(values.get(0).toString()));
}
break;
case "userOwner":
case "groupOwner":
if (anyTO instanceof GroupTO && attr != null) {
// using a special attribute (with schema "", that will be ignored) for carrying the
// GroupOwnerSchema value
AttrTO attrTO = new AttrTO();
attrTO.setSchema(StringUtils.EMPTY);
if (values.isEmpty() || values.get(0) == null) {
attrTO.getValues().add(StringUtils.EMPTY);
} else {
attrTO.getValues().add(values.get(0).toString());
}
((GroupTO) anyTO).getPlainAttrs().add(attrTO);
}
break;
default:
}
} else if (intAttrName.getSchemaType() != null) {
GroupableRelatableTO groupableTO = null;
Group group = null;
if (anyTO instanceof GroupableRelatableTO && intAttrName.getMembershipOfGroup() != null) {
groupableTO = (GroupableRelatableTO) anyTO;
group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
}
switch(intAttrName.getSchemaType()) {
case PLAIN:
AttrTO attrTO = new AttrTO();
attrTO.setSchema(intAttrName.getSchemaName());
PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
for (Object value : values) {
AttrSchemaType schemaType = schema == null ? AttrSchemaType.String : schema.getType();
if (value != null) {
PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
switch(schemaType) {
case String:
attrValue.setStringValue(value.toString());
break;
case Binary:
attrValue.setBinaryValue((byte[]) value);
break;
default:
try {
attrValue.parseValue(schema, value.toString());
} catch (ParsingValidationException e) {
LOG.error("While parsing provided value {}", value, e);
attrValue.setStringValue(value.toString());
schemaType = AttrSchemaType.String;
}
break;
}
attrTO.getValues().add(attrValue.getValueAsString(schemaType));
}
}
if (groupableTO == null || group == null) {
anyTO.getPlainAttrs().add(attrTO);
} else {
Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
if (!membership.isPresent()) {
membership = Optional.of(new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
groupableTO.getMemberships().add(membership.get());
}
membership.get().getPlainAttrs().add(attrTO);
}
break;
case DERIVED:
attrTO = new AttrTO();
attrTO.setSchema(intAttrName.getSchemaName());
if (groupableTO == null || group == null) {
anyTO.getDerAttrs().add(attrTO);
} else {
Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
if (!membership.isPresent()) {
membership = Optional.of(new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
groupableTO.getMemberships().add(membership.get());
}
membership.get().getDerAttrs().add(attrTO);
}
break;
case VIRTUAL:
attrTO = new AttrTO();
attrTO.setSchema(intAttrName.getSchemaName());
// virtual attributes don't get transformed, iterate over original attr.getValue()
if (attr != null && attr.getValue() != null && !attr.getValue().isEmpty()) {
attr.getValue().stream().filter(value -> value != null).forEachOrdered(value -> attrTO.getValues().add(value.toString()));
}
if (groupableTO == null || group == null) {
anyTO.getVirAttrs().add(attrTO);
} else {
Optional<MembershipTO> membership = groupableTO.getMembership(group.getKey());
if (!membership.isPresent()) {
membership = Optional.of(new MembershipTO.Builder().group(group.getKey(), group.getName()).build());
groupableTO.getMemberships().add(membership.get());
}
membership.get().getVirAttrs().add(attrTO);
}
break;
default:
}
}
}
use of org.identityconnectors.framework.common.objects.Attribute in project syncope by apache.
the class AbstractPropagationTaskExecutor method execute.
protected TaskExec execute(final PropagationTaskTO taskTO, final PropagationReporter reporter) {
PropagationTask task = entityFactory.newEntity(PropagationTask.class);
task.setResource(resourceDAO.find(taskTO.getResource()));
task.setObjectClassName(taskTO.getObjectClassName());
task.setAnyTypeKind(taskTO.getAnyTypeKind());
task.setAnyType(taskTO.getAnyType());
task.setEntityKey(taskTO.getEntityKey());
task.setOperation(taskTO.getOperation());
task.setConnObjectKey(taskTO.getConnObjectKey());
task.setOldConnObjectKey(taskTO.getOldConnObjectKey());
Set<Attribute> attributes = new HashSet<>();
if (StringUtils.isNotBlank(taskTO.getAttributes())) {
attributes.addAll(Arrays.asList(POJOHelper.deserialize(taskTO.getAttributes(), Attribute[].class)));
}
task.setAttributes(attributes);
List<PropagationActions> actions = getPropagationActions(task.getResource());
String resource = task.getResource().getKey();
Date start = new Date();
TaskExec execution = entityFactory.newEntity(TaskExec.class);
execution.setStatus(PropagationTaskExecStatus.CREATED.name());
String taskExecutionMessage = null;
String failureReason = null;
// Flag to state whether any propagation has been attempted
AtomicReference<Boolean> propagationAttempted = new AtomicReference<>(false);
ConnectorObject beforeObj = null;
ConnectorObject afterObj = null;
Provision provision = null;
OrgUnit orgUnit = null;
Uid uid = null;
Connector connector = null;
Result result;
try {
provision = task.getResource().getProvision(new ObjectClass(task.getObjectClassName())).orElse(null);
orgUnit = task.getResource().getOrgUnit();
connector = connFactory.getConnector(task.getResource());
// Try to read remote object BEFORE any actual operation
beforeObj = provision == null && orgUnit == null ? null : orgUnit == null ? getRemoteObject(task, connector, provision, false) : getRemoteObject(task, connector, orgUnit, false);
for (PropagationActions action : actions) {
action.before(task, beforeObj);
}
switch(task.getOperation()) {
case CREATE:
case UPDATE:
uid = createOrUpdate(task, beforeObj, connector, propagationAttempted);
break;
case DELETE:
uid = delete(task, beforeObj, connector, propagationAttempted);
break;
default:
}
execution.setStatus(propagationAttempted.get() ? PropagationTaskExecStatus.SUCCESS.name() : PropagationTaskExecStatus.NOT_ATTEMPTED.name());
LOG.debug("Successfully propagated to {}", task.getResource());
result = Result.SUCCESS;
} catch (Exception e) {
result = Result.FAILURE;
LOG.error("Exception during provision on resource " + resource, e);
if (e instanceof ConnectorException && e.getCause() != null) {
taskExecutionMessage = e.getCause().getMessage();
if (e.getCause().getMessage() == null) {
failureReason = e.getMessage();
} else {
failureReason = e.getMessage() + "\n\n Cause: " + e.getCause().getMessage().split("\n")[0];
}
} else {
taskExecutionMessage = ExceptionUtils2.getFullStackTrace(e);
if (e.getCause() == null) {
failureReason = e.getMessage();
} else {
failureReason = e.getMessage() + "\n\n Cause: " + e.getCause().getMessage().split("\n")[0];
}
}
try {
execution.setStatus(PropagationTaskExecStatus.FAILURE.name());
} catch (Exception wft) {
LOG.error("While executing KO action on {}", execution, wft);
}
propagationAttempted.set(true);
actions.forEach(action -> {
action.onError(task, execution, e);
});
} finally {
// Try to read remote object AFTER any actual operation
if (connector != null) {
if (uid != null) {
task.setConnObjectKey(uid.getUidValue());
}
try {
afterObj = provision == null && orgUnit == null ? null : orgUnit == null ? getRemoteObject(task, connector, provision, true) : getRemoteObject(task, connector, orgUnit, true);
} catch (Exception ignore) {
// ignore exception
LOG.error("Error retrieving after object", ignore);
}
}
if (task.getOperation() != ResourceOperation.DELETE && afterObj == null && uid != null) {
afterObj = new ConnectorObjectBuilder().setObjectClass(new ObjectClass(task.getObjectClassName())).setUid(uid).setName(AttributeUtil.getNameFromAttributes(task.getAttributes())).build();
}
execution.setStart(start);
execution.setMessage(taskExecutionMessage);
execution.setEnd(new Date());
LOG.debug("Execution finished: {}", execution);
if (hasToBeregistered(task, execution)) {
LOG.debug("Execution to be stored: {}", execution);
execution.setTask(task);
task.add(execution);
taskDAO.save(task);
// needed to generate a value for the execution key
taskDAO.flush();
}
if (reporter != null) {
reporter.onSuccessOrNonPriorityResourceFailures(taskTO, PropagationTaskExecStatus.valueOf(execution.getStatus()), failureReason, beforeObj, afterObj);
}
}
for (PropagationActions action : actions) {
action.after(task, execution, afterObj);
}
// SYNCOPE-1136
String anyTypeKind = task.getAnyTypeKind() == null ? "realm" : task.getAnyTypeKind().name().toLowerCase();
String operation = task.getOperation().name().toLowerCase();
boolean notificationsAvailable = notificationManager.notificationsAvailable(AuditElements.EventCategoryType.PROPAGATION, anyTypeKind, resource, operation);
boolean auditRequested = auditManager.auditRequested(AuditElements.EventCategoryType.PROPAGATION, anyTypeKind, resource, operation);
if (notificationsAvailable || auditRequested) {
ExecTO execTO = taskDataBinder.getExecTO(execution);
notificationManager.createTasks(AuditElements.EventCategoryType.PROPAGATION, anyTypeKind, resource, operation, result, beforeObj, new Object[] { execTO, afterObj }, taskTO);
auditManager.audit(AuditElements.EventCategoryType.PROPAGATION, anyTypeKind, resource, operation, result, beforeObj, new Object[] { execTO, afterObj }, taskTO);
}
return execution;
}
use of org.identityconnectors.framework.common.objects.Attribute in project syncope by apache.
the class AbstractPropagationTaskExecutor method createOrUpdate.
protected Uid createOrUpdate(final PropagationTask task, final ConnectorObject beforeObj, final Connector connector, final AtomicReference<Boolean> propagationAttempted) {
// set of attributes to be propagated
Set<Attribute> attributes = new HashSet<>(task.getAttributes());
// check if there is any missing or null / empty mandatory attribute
Set<Object> mandatoryAttrNames = new HashSet<>();
Attribute mandatoryMissing = AttributeUtil.find(MANDATORY_MISSING_ATTR_NAME, task.getAttributes());
if (mandatoryMissing != null) {
attributes.remove(mandatoryMissing);
if (beforeObj == null) {
mandatoryAttrNames.addAll(mandatoryMissing.getValue());
}
}
Attribute mandatoryNullOrEmpty = AttributeUtil.find(MANDATORY_NULL_OR_EMPTY_ATTR_NAME, task.getAttributes());
if (mandatoryNullOrEmpty != null) {
attributes.remove(mandatoryNullOrEmpty);
mandatoryAttrNames.addAll(mandatoryNullOrEmpty.getValue());
}
if (!mandatoryAttrNames.isEmpty()) {
throw new IllegalArgumentException("Not attempted because there are mandatory attributes without value(s): " + mandatoryAttrNames);
}
Uid result;
if (beforeObj == null) {
LOG.debug("Create {} on {}", attributes, task.getResource().getKey());
result = connector.create(new ObjectClass(task.getObjectClassName()), attributes, null, propagationAttempted);
} else {
// 1. check if rename is really required
Name newName = AttributeUtil.getNameFromAttributes(attributes);
LOG.debug("Rename required with value {}", newName);
if (newName != null && newName.equals(beforeObj.getName()) && !newName.getNameValue().equals(beforeObj.getUid().getUidValue())) {
LOG.debug("Remote object name unchanged");
attributes.remove(newName);
}
// 2. check wether anything is actually needing to be propagated, i.e. if there is attribute
// difference between beforeObj - just read above from the connector - and the values to be propagated
Map<String, Attribute> originalAttrMap = beforeObj.getAttributes().stream().collect(Collectors.toMap(attr -> attr.getName().toUpperCase(), attr -> attr));
Map<String, Attribute> updateAttrMap = attributes.stream().collect(Collectors.toMap(attr -> attr.getName().toUpperCase(), attr -> attr));
// Only compare attribute from beforeObj that are also being updated
Set<String> skipAttrNames = originalAttrMap.keySet();
skipAttrNames.removeAll(updateAttrMap.keySet());
new HashSet<>(skipAttrNames).forEach(attrName -> {
originalAttrMap.remove(attrName);
});
Set<Attribute> originalAttrs = new HashSet<>(originalAttrMap.values());
if (originalAttrs.equals(attributes)) {
LOG.debug("Don't need to propagate anything: {} is equal to {}", originalAttrs, attributes);
result = AttributeUtil.getUidAttribute(attributes);
} else {
LOG.debug("Attributes that would be updated {}", attributes);
Set<Attribute> strictlyModified = new HashSet<>();
attributes.stream().filter(attr -> (!originalAttrs.contains(attr))).forEachOrdered(attr -> {
strictlyModified.add(attr);
});
// 3. provision entry
LOG.debug("Update {} on {}", strictlyModified, task.getResource().getKey());
result = connector.update(beforeObj.getObjectClass(), new Uid(beforeObj.getUid().getUidValue()), strictlyModified, null, propagationAttempted);
}
}
return result;
}
use of org.identityconnectors.framework.common.objects.Attribute in project syncope by apache.
the class ResourceLogic method readConnObject.
@PreAuthorize("hasRole('" + StandardEntitlement.RESOURCE_GET_CONNOBJECT + "')")
@Transactional(readOnly = true)
public ConnObjectTO readConnObject(final String key, final String anyTypeKey, final String anyKey) {
Triple<ExternalResource, AnyType, Provision> init = connObjectInit(key, anyTypeKey);
// 1. find any
Any<?> any = init.getMiddle().getKind() == AnyTypeKind.USER ? userDAO.find(anyKey) : init.getMiddle().getKind() == AnyTypeKind.ANY_OBJECT ? anyObjectDAO.find(anyKey) : groupDAO.find(anyKey);
if (any == null) {
throw new NotFoundException(init.getMiddle() + " " + anyKey);
}
// 2. build connObjectKeyItem
Optional<MappingItem> connObjectKeyItem = MappingUtils.getConnObjectKeyItem(init.getRight());
if (!connObjectKeyItem.isPresent()) {
throw new NotFoundException("ConnObjectKey mapping for " + init.getMiddle() + " " + anyKey + " on resource '" + key + "'");
}
Optional<String> connObjectKeyValue = mappingManager.getConnObjectKeyValue(any, init.getRight());
// 3. determine attributes to query
Set<MappingItem> linkinMappingItems = virSchemaDAO.findByProvision(init.getRight()).stream().map(virSchema -> virSchema.asLinkingMappingItem()).collect(Collectors.toSet());
Iterator<MappingItem> mapItems = new IteratorChain<>(init.getRight().getMapping().getItems().iterator(), linkinMappingItems.iterator());
// 4. read from the underlying connector
Connector connector = connFactory.getConnector(init.getLeft());
ConnectorObject connectorObject = connector.getObject(init.getRight().getObjectClass(), AttributeBuilder.build(connObjectKeyItem.get().getExtAttrName(), connObjectKeyValue.get()), MappingUtils.buildOperationOptions(mapItems));
if (connectorObject == null) {
throw new NotFoundException("Object " + connObjectKeyValue.get() + " with class " + init.getRight().getObjectClass() + " not found on resource " + key);
}
// 5. build result
Set<Attribute> attributes = connectorObject.getAttributes();
if (AttributeUtil.find(Uid.NAME, attributes) == null) {
attributes.add(connectorObject.getUid());
}
if (AttributeUtil.find(Name.NAME, attributes) == null) {
attributes.add(connectorObject.getName());
}
return ConnObjectUtils.getConnObjectTO(connectorObject);
}
Aggregations