Hi,
in [1] you are affirming that the derived attribute "accountName" is defined as

"'adm-'+personId"

where personId is a USER attribute. Moreover, from [3] I guess that accountName 
is actually a membership attribute: so, a USER attribute but related to the 
membership of a given group (appAdmin2 in this case).

From mapping [2] I can see the you are referring to it as

groups[appAdmin2].accountName

where, according to

https://syncope.apache.org/docs/4.0/reference-guide.html#mapping

accountName is a group attribute, taken from group appAdmin2.

Hence, we have a USER derived attribute that should be evaluated against a 
GROUP attribute.

This is not going to work: derived attributes are evaluated in the context of 
the owning side: USER derived attributes against the owning user, GROUP derived 
attributes against the owning group, not mixin.

The fix from SYNCOPE-1944 is now evaluating membership derived attributes 
against membership plain attributes, which was not happening before.
If you are curious to see what is the expected outcome of the fix from 
SYNCOPE-1944, then you need to take a look at the test case that was added for 
such a purpose:

https://github.com/apache/syncope/blob/4_0_X/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java#L347-L371

The whole schema and mapping definitions can work as pure configuration up to a 
certain point: for every further need - including yours. presumably - Syncope 
is providing hooks to customize the process; if you have special needs, then 
probably it is best to code a

https://syncope.apache.org/docs/4.0/reference-guide.html#propagationactions

class in Java or Groovy.

Hope this clarifies.
Regards.

On 28/01/26 23:04, Stéphane Popoff wrote:
Hi,

The issue SYNCOPE-1944 report fixing derived attribute management for
memberships in 4.0.4 version.
My test with version 4.0.4-SNAPSHOT won't validate the fix.
- the derived attribute [1]
- the usage of the derived attribute in resource admin2 [2]
- the log [4] of the creation of an account adm-toto with appAdmin2's membership
- the user adm-toto after the propagation [3]
[1] {
     "_class": "org.apache.syncope.common.lib.to.DerSchemaTO",
     "key": "accountName",
     "expression": "'adm-'+personId" // personId come from USER
}

[2]                         {
                             "intAttrName": "groups[appAdmin2].accountName",
                             "extAttrName": "login",
                             "connObjectKey": false,
                             "password": false,
                             "mandatoryCondition": "false",
                             "purpose": "PROPAGATION",
                             "propagationJEXLTransformer": null,
                             "pullJEXLTransformer": null,
                             "transformers": []
                         },
[3] {
     "_class": "org.apache.syncope.common.lib.to.UserTO",
     "key": "019c068c-ba88-727d-8182-4e36314e3085",
     "type": "USER",
     "realm": "/",
     "username": "adm-toto",
.....
     "status": "active",
     "auxClasses": [],
     "plainAttrs": [
         {
             "schema": "nom",
             "values": [
                 "TO"
             ]
         },
         {
             "schema": "personId",
             "values": [
                 "toto"
             ]
         },
         {
             "schema": "prenom",
             "values": [
                 "to"
             ]
         }
     ],
     "derAttrs": [],
     "resources": [
         "admin2"
     ],
     .....
     "memberships": [
         {
             "groupKey": "019c068c-2644-76db-b110-6f31bec3c2d9",
             "groupName": "appAdmin2",
             "plainAttrs": [
                 {
                     "schema": "appName",
                     "values": [
                         "appli2"
                     ]
                 },
                 {
                     "schema": "login",
                     "values": [
                         "usr-tonton"
                     ]
                 },
                 {
                     "schema": "projects",
                     "values": [
                         "pj1",
                         "pj2"
                     ]
                 }
             ],
             "derAttrs": [
                 {
                     "schema": "accountName",
                     "values": [
                         "adm-"
                     ]
                 }
             ]
         }
     ],
     ....
}

[4] 2026-01-28 21:41:39.838 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Create
script loaded Method: init
2026-01-28 21:41:39.911 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Update
script loaded Method: init
2026-01-28 21:41:39.955 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Delete
script loaded Method: init
2026-01-28 21:41:40.072 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Search
script loaded Method: init
2026-01-28 21:41:40.167 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Sync
script loaded   Method: init
2026-01-28 21:41:40.281 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Schema
script loaded Method: init
2026-01-28 21:41:40.316 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Test
script loaded   Method: init
2026-01-28 21:41:40.317 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector :
Connector net.tirasa.connid.bundles.rest.RESTConnector successfully
inited   Method: init
2026-01-28 21:41:40.317 DEBUG [eExecutor-5]
org.identityconnectors.framework.spi.operations.CreateOp     :
instance='RestAdmin2' Enter: create(ObjectClass: __ACCOUNT__,
[Attribute: {Name=projects, Value=[pj1, pj2]}, Attribute:
{Name=appName, Value=[appli2]}, Attribute: {Name=login, Value=[adm-]},
Attribute: {Name=__NAME__,
Value=[019c068c-ba88-727d-8182-4e36314e3085]}], OperationOptions: {})
   Method: create
2026-01-28 21:41:40.317 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Object
class: __ACCOUNT__    Method: create
2026-01-28 21:41:40.324  INFO [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector :
Entering CREATE Script       Method: invoke
2026-01-28 21:41:40.350 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Sending
POST to http://admins2:48080/admins/adda with payload
{"login":"adm-","key":"019c068c-ba88-727d-8182-4e36314e3085","appName":"appli2","projects":["pj1","pj2"]}
Method: invoke
2026-01-28 21:41:40.372 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector : Create
response: 200 {Content-Length=[147], content-type=[application/json],
date=[Wed, 28 Jan 2026 21:41:40 GMT], Content-Type=[application/json]}
     Method: invoke
2026-01-28 21:41:40.374 DEBUG [eExecutor-5]
net.tirasa.connid.commons.scripted.AbstractScriptedConnector :
019c068c-ba88-727d-8182-4e36314e3085 created Method: create
2026-01-28 21:41:40.375 DEBUG [eExecutor-5]
org.identityconnectors.framework.spi.operations.CreateOp     :
instance='RestAdmin2' Return: Attribute: {Name=__UID__,
Value=[019c068c-ba88-727d-8182-4e36314e3085]}   Method: create
2026-01-28 21:41:40.376 DEBUG [eExecutor-5]
org.identityconnectors.framework.api.operations.CreateApiOp  : Return:
Attribute: {Name=__UID__,
Value=[019c068c-ba88-727d-8182-4e36314e3085]}M


--
Francesco Chicchiriccò

Tirasa - Open Source Excellence
http://www.tirasa.net/

Member at The Apache Software Foundation
Syncope, Cocoon, Olingo, CXF, OpenJPA
https://about.me/ilgrosso

Reply via email to