Hi Francesco,

I try to implement the solution based on User and group only. I found
a solution with a resource that accepts both groups and user. I'm
waiting for version 4.0.4 to integrate the derived attribute
evaluation.
In the resource joined [1] I use a simple plain attribute, but how can
I make the propagate attribute more dynamic ?
(groups[appAdmin].appName change appAdmin by something else)

[1] {
    "key": "admin",
    "connector": "019be54f-fec3-7403-b739-f82d00f6012f",
    "connectorDisplayName": "RestAdmin",
    "provisions": [
        {
            "anyType": "GROUP",
            "objectClass": "__GROUP__",
            "auxClasses": [
                "AdminGroup"
            ],
            "syncToken": null,
            "ignoreCaseMatch": false,
            "uidOnCreate": null,
            "mapping": {
                "items": [
                    {
                        "intAttrName": "name",
                        "extAttrName": "appName",
                        "connObjectKey": true,
                        "password": false,
                        "mandatoryCondition": "true",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "key",
                        "extAttrName": "key",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "groups[appAdmin].projects",
                        "extAttrName": "projects",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "PROPAGATION",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "groups[appAdmin].appName",
                        "extAttrName": "appName",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "PROPAGATION",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    }
                ],
                "connObjectLink": null
            }
        },
        {
            "anyType": "USER",
            "objectClass": "__ACCOUNT__",
            "auxClasses": [
                "AdminGroup"
            ],
            "syncToken": null,
            "ignoreCaseMatch": false,
            "uidOnCreate": null,
            "mapping": {
                "items": [
                    {
                        "intAttrName": "username",
                        "extAttrName": "login",
                        "connObjectKey": true,
                        "password": false,
                        "mandatoryCondition": "true",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "appName",
                        "extAttrName": "appName",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "key",
                        "extAttrName": "key",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "login",
                        "extAttrName": "login",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "projects",
                        "extAttrName": "projects",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "BOTH",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "groups[appAdmin].appName",
                        "extAttrName": "appName",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "PROPAGATION",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    },
                    {
                        "intAttrName": "groups[appAdmin].projects",
                        "extAttrName": "projects",
                        "connObjectKey": false,
                        "password": false,
                        "mandatoryCondition": "false",
                        "purpose": "PROPAGATION",
                        "propagationJEXLTransformer": null,
                        "pullJEXLTransformer": null,
                        "transformers": []
                    }
                ],
                "connObjectLink": null
            }
        }
    ],
    "orgUnit": null,
    "propagationPriority": 10,
    "enforceMandatoryCondition": true,
    "createTraceLevel": "ALL",
    "updateTraceLevel": "ALL",
    "deleteTraceLevel": "ALL",
    "provisioningTraceLevel": "ALL",
    "passwordPolicy": null,
    "accountPolicy": null,
    "propagationPolicy": null,
    "inboundPolicy": null,
    "pushPolicy": null,
    "provisionSorter": null,
    "authPolicy": null,
    "accessPolicy": null,
    "confOverrideFlag": true,
    "confOverrideValue": [],
    "capabilitiesOverrideFlag": false,
    "capabilitiesOverrideValue": null,
    "propagationActions": []
}

Le jeu. 15 janv. 2026 à 14:53, Stéphane Popoff <[email protected]> a écrit :
>
> Hi Francesco,
>
> The case of Mr Bellini is very interesting, because in my view,
> informations came from both side:
> - the emails MX come from the IT university team (Group)
> groups['University A'].mx="@university_a.net"
> - the email identifier come from the Identity username (User) 
> username="bellini"
> Suppose that a resource is joined with the group "University A" and
> "University B". So without human access to attributes, how can that
> information be propagated to emails servers scripts to produce 2
> different mailboxes ?
> Where should I put this derived attribute: mail=username+mx, and when
> did it be evaluated for use in a provisioning process of the email
> resource ?
>
> I'm sorry to insist, but if I had found more explanation on this use
> case in the documentation, I wouldn't have brought it up again.
>
> Best regards
> Stéphane POPOFF
>
> Le jeu. 15 janv. 2026 à 13:08, Francesco Chicchiriccò
> <[email protected]> a écrit :
> >
> > Hi,
> > I saw SYNCOPE-1944 but I had to fix the content.
> >
> > Let me repeat again that the purpose of Type Extension is not to copy 
> > Group's attributes to members (Users or Any Objects) but to define 
> > additional attributes that members will be able to hold, once a membership 
> > exists.
> >
> > With reference to the example given in
> >
> > https://syncope.apache.org/docs/4.0/reference-guide.html#type-extensions
> >
> > The user bellini has two email addresses, one for Membership with GROUP for 
> > University A and one for Membership with GROUP for University B, but such 
> > emails addresses had to be provided when creating or updating the user 
> > bellini and are related to bellini itself, not the universities.
> >
> > The example is supposing that the Type Extensions for both university 
> > groups are allowing the same email address for their members.
> >
> >
> > Besides this, in case you need to consider group attributes (not membership 
> > attributes) for Resource Mapping, you can use the syntax as explained by
> >
> > https://syncope.apache.org/docs/4.0/reference-guide.html#mapping
> >
> > e.g.
> >
> > groups[groupName].schema
> >
> > Hope this clarifies.
> > Regards.
> >
> > On 15/01/26 08:45, Francesco Chicchiriccò wrote:
> > > Hi,
> > > by looking at the code, I think that derived attributes are not working 
> > > correctly for memberships (as driven by group's type extension): please 
> > > go ahead and open an issue on JIRA.
> > >
> > > Regarding plain attributes for memberships, instead, please consider that 
> > > (a) Syncope will not store not return attributes with empty value and (b) 
> > > it is up to the caller to provide such values when creating or updating 
> > > the membership.
> > >
> > > Regards.
> > >
> > > On 14/01/26 12:51, Stéphane Popoff wrote:
> > >> Hi Francesco,
> > >>
> > >> I see an explanation about Type Extensions in the reference guide. I
> > >> created  a group appAdmin with Type Extension [1] but when applying
> > >> the group to a user some attributes fail or don't appear [2].
> > >> My question is how the Type Extension attribute can be evaluated when
> > >> a group is associated with a user ? The case is the derived attribute:
> > >> login = "'adm'+personId".
> > >>
> > >> Best regards,
> > >> Stéphane POPOFF
> > >>
> > >> [1] {
> > >>      "_class": "org.apache.syncope.common.lib.to.GroupTO",
> > >>      "key": "019bbbf3-7b9f-7b6b-aa1c-6a210de2f615",
> > >>      "type": "GROUP",
> > >>      "realm": "/",
> > >>      "name": "appAdmin",
> > >>      "creator": "admin",
> > >>      "creationDate": "2026-01-14T10:00:55.025528Z",
> > >>      "creationContext": "REST",
> > >>      "lastModifier": "admin",
> > >>      "lastChangeDate": "2026-01-14T11:30:03.36464Z",
> > >>      "lastChangeContext": "REST",
> > >>      "dynRealms": [],
> > >>      "status": null,
> > >>      "auxClasses": [
> > >>          "AdminGroup"
> > >>      ],
> > >>      "plainAttrs": [
> > >>          {
> > >>              "schema": "projects",
> > >>              "values": [
> > >>                  "projet1",
> > >>                  "projet2"
> > >>              ]
> > >>          }
> > >>      ],
> > >>      "derAttrs": [
> > >>          {
> > >>              "schema": "login",
> > >>              "values": [
> > >>                  "adm-"
> > >>              ]
> > >>          }
> > >>      ],
> > >>      "resources": [
> > >>          "admin"
> > >>      ],
> > >>      "relationships": [],
> > >>      "userOwner": null,
> > >>      "groupOwner": null,
> > >>      "udynMembershipCond": null,
> > >>      "staticUserMembershipCount": 4,
> > >>      "dynamicUserMembershipCount": 0,
> > >>      "staticAnyObjectMembershipCount": 0,
> > >>      "dynamicAnyObjectMembershipCount": 0,
> > >>      "adynMembershipConds": {},
> > >>      "typeExtensions": [
> > >>          {
> > >>              "anyType": "USER",
> > >>              "auxClasses": [
> > >>                  "AdminGroup"
> > >>              ]
> > >>          }
> > >>      ]
> > >> }
> > >> [2] {
> > >>      "_class": "org.apache.syncope.common.lib.to.UserTO",
> > >>      "key": "019bbbf4-232d-70e1-b940-1f091e4be34c",
> > >>      "type": "USER",
> > >>      "realm": "/",
> > >>      "username": "tutu",
> > >>      "creator": "admin",
> > >>      "creationDate": "2026-01-14T10:01:37.940487Z",
> > >>      "creationContext": "PULL Task 019bbbf1-7f0f-7935-b0c8-534be438ec42
> > >> 'chargePersons'",
> > >>      "lastModifier": "tutu",
> > >>      "lastChangeDate": "2026-01-14T11:33:16.231655284Z",
> > >>      "lastChangeContext": "REST",
> > >>      "dynRealms": [],
> > >>      "status": "active",
> > >>      "auxClasses": [],
> > >>      "plainAttrs": [
> > >>          {
> > >>              "schema": "nom",
> > >>              "values": [
> > >>                  "nom de tutu"
> > >>              ]
> > >>          },
> > >>          {
> > >>              "schema": "operationalUnit",
> > >>              "values": [
> > >>                  "boulot"
> > >>              ]
> > >>          },
> > >>          {
> > >>              "schema": "personId",
> > >>              "values": [
> > >>                  "tutu"
> > >>              ]
> > >>          },
> > >>          {
> > >>              "schema": "prenom",
> > >>              "values": [
> > >>                  "prénom de tutu"
> > >>              ]
> > >>          }
> > >>      ],
> > >>      "derAttrs": [],
> > >>      "resources": [
> > >>          "admin"
> > >>      ],
> > >>      "relationships": [],
> > >>      "password": null,
> > >>      "token": null,
> > >>      "tokenExpireTime": null,
> > >>      "lastLoginDate": "2026-01-14T11:32:54.613387809Z",
> > >>      "changePwdDate": "2026-01-14T11:32:19.490419976Z",
> > >>      "failedLogins": 0,
> > >>      "securityQuestion": null,
> > >>      "securityAnswer": null,
> > >>      "suspended": false,
> > >>      "mustChangePassword": false,
> > >>      "memberships": [
> > >>          {
> > >>              "groupKey": "019bbbf3-7b9f-7b6b-aa1c-6a210de2f615",
> > >>              "groupName": "appAdmin",
> > >>              "plainAttrs": [],  //where are projects values ?
> > >>              "derAttrs": [
> > >>                  {
> > >>                      "schema": "login",
> > >>                      "values": [
> > >>                          "adm-"    //should be adm-tutu
> > >>                      ]
> > >>                  }
> > >>              ]
> > >>          }
> > >>      ],
> > >>      "dynMemberships": [],
> > >>      "roles": [],
> > >>      "dynRoles": [],
> > >>      "linkedAccounts": [],
> > >>      "delegatingDelegations": [],
> > >>      "delegatedDelegations": []
> > >> }
> > >>
> > >> Le ven. 9 janv. 2026 à 08:17, Francesco Chicchiriccò
> > >> <[email protected]> a écrit :
> > >>> Hi,
> > >>> I wouldn't say that Syncope is based on accounts, rather the opposite.
> > >>>
> > >>> I would also designed differently your use case, based on Syncope 
> > >>> features:
> > >>>
> > >>> * no need for PERSON, just stick to USER
> > >>> *     define a Group for each application, where:
> > >>>      * the Type Extension for the Group contains all user attributes 
> > >>> required by the application
> > >>>      * the External Resource is assigned to the Group, not the single 
> > >>> User, where the mapping of such External Resource is based on both USER 
> > >>> and Membership attributes (as defined by the Type Extension)
> > >>>
> > >>> Now, when a user needs to be assigned to an application, a membership 
> > >>> will be created and the given user will be propagated to the Resource 
> > >>> assigned to the Group for the membership.
> > >>> No need for any code customization.
> > >>>
> > >>> HTH
> > >>> Regards.
> > >>>
> > >>> On 08/01/26 12:42, Stéphane Popoff wrote:
> > >>>> Hi Francesco,
> > >>>>
> > >>>> My english is also poor, so that explains some misunderstanding.
> > >>>>
> > >>>> Basically one PERSON instance like 'titi' (personId="titi") may have
> > >>>> many accounts (User instance) like: 'usr-titi', 'adm-titi' ...
> > >>>> PERSON titi have their own lifecycle, managed by an external resource
> > >>>> like an HR System (see https://github.com/spopoff/persons).
> > >>>> So when an event of create / update / delete appears on 'titi', a
> > >>>> "business" logic should apply rules that modify accounts.
> > >>>> For example:
> > >>>> - When 'toto' is created, we creates an account 'usr-toto' with
> > >>>> minimal access to some applications
> > >>>> - When 'toto' is updated and this operationalUnit attribute equals
> > >>>> "SOC", we creates a new account 'adm-toto' with privilege access
> > >>>> - When 'toto' quit, is deleted, all the associate accounts are deleted
> > >>>> (based on the value 'toto' in the attribute personName)
> > >>>>
> > >>>> Actually I put this "Business" logic (create /delete) in an extension
> > >>>> of DefaultAnyObjectProvisioningManager (see code below). But are there
> > >>>> the best implementations ?
> > >>>> Generally this "Business" logic takes place in a workflow, I also
> > >>>> extend DefaultAnyObjectWorkflowAdapter, but I found a problem with the
> > >>>> delete. It's also very deep in Syncope and not user friendly (pure
> > >>>> Java code).
> > >>>> My view on Syncope is that it's a good tool for synchronizing
> > >>>> resources and accounts, and also for authenticating those resources
> > >>>> and their accounts. However, its account-centric approach makes it
> > >>>> difficult to integrate an identity-oriented logic.
> > >>>> At this point in my thinking, I believe that part of the logic needs
> > >>>> to be put upstream of Syncope and APIs used to control access
> > >>>> management.
> > >>>> What did you think ?
> > >>>>
> > >>>> Best regards,
> > >>>>
> > >>>> Stéphane POPOFF
> > >>>>
> > >>>> public class PersonProvisioningManager extends
> > >>>> DefaultAnyObjectProvisioningManager {
> > >>>>       @Autowired
> > >>>>       UserProvisioningManager userProvisioningManager;
> > >>>>       @Autowired
> > >>>>       protected UserDAO userDAO;
> > >>>>       protected static final Logger LOG =
> > >>>> LogManager.getLogger(PersonProvisioningManager.class);
> > >>>>       public PersonProvisioningManager(AnyObjectWorkflowAdapter
> > >>>> awfAdapter, PropagationManager propagationManager,
> > >>>> PropagationTaskExecutor taskExecutor, AnyObjectDAO anyObjectDAO) {
> > >>>>           super(awfAdapter, propagationManager, taskExecutor, 
> > >>>> anyObjectDAO);
> > >>>>       }
> > >>>>       @Transactional(propagation = Propagation.REQUIRES_NEW)
> > >>>>       @Override
> > >>>>       public ProvisioningResult<String> create(
> > >>>>               final AnyObjectCR anyObjectCR,
> > >>>>               final Set<String> excludedResources,
> > >>>>               final boolean nullPriorityAsync,
> > >>>>               final String creator,
> > >>>>               final String context){
> > >>>>           //on teste si c'est un objet PERSON car alors on va peut-être
> > >>>> créer un compte d'accès primaire
> > >>>>           if(!anyObjectCR.getType().equals("PERSON")){
> > >>>>              LOG.info("pas un objet PERSON <> "+anyObjectCR.getType());
> > >>>>              return super.create(anyObjectCR, excludedResources,
> > >>>> nullPriorityAsync, creator, context);
> > >>>>           }
> > >>>>           LOG.info("1 Création d'une personne 
> > >>>> name="+anyObjectCR.getName());
> > >>>>           //on fait appel au workflow objet qui reconnait les PERSON
> > >>>>           WorkflowResult<String> created =
> > >>>> awfAdapter.create(anyObjectCR, creator, context);
> > >>>>           LOG.info("retour du workflow "+created.getResult());
> > >>>>           //je sais pas ce qu'il raconte en cas de réussite ou échec ?
> > >>>>           //on cherche un USER avec un personId == 
> > >>>> anyObjectCR.getName();
> > >>>>           List<User> users = null;
> > >>>>           boolean erreur = false;
> > >>>>           try{
> > >>>>               users = userDAO.findByDerAttrValue("personName==",
> > >>>> anyObjectCR.getName(), false);
> > >>>>           }catch(Exception ex){
> > >>>>               LOG.error("Erreur recherche USER "+ex);
> > >>>>               erreur = true;
> > >>>>           }
> > >>>>           if(!erreur && users != null && !users.isEmpty()){
> > >>>>               //on trouve un des comptes
> > >>>>               LOG.info("2 Déjà des comptes, mais conforme aux besoins 
> > >>>> métiers ?");
> > >>>>           }else if(!erreur){
> > >>>>               LOG.info("2 Pas comptes, mais répondre aux besoins 
> > >>>> métiers ?");
> > >>>>               UserCR novo = new UserCR.Builder("/", 
> > >>>> "usr-"+anyObjectCR.getName())
> > >>>>                       .plainAttr(new
> > >>>> Attr.Builder("personName").value(anyObjectCR.getName()).build()).build();
> > >>>>               userProvisioningManager.create(novo, nullPriorityAsync,
> > >>>> creator, context);
> > >>>>           }
> > >>>>           //Je sais pas encore comment gérer cette partie
> > >>>>           List<PropagationTaskInfo> taskInfos = 
> > >>>> propagationManager.getCreateTasks(
> > >>>>                   AnyTypeKind.ANY_OBJECT,
> > >>>>                   created.getResult(),
> > >>>>                   null,
> > >>>>                   created.getPropByRes(),
> > >>>>                   excludedResources);
> > >>>>           //en fait je retourne zéro pour l'instant
> > >>>>           LOG.info("3 Taches de propagation nb="+taskInfos.size());
> > >>>>           for(PropagationTaskInfo taskInfo : taskInfos){
> > >>>>               LOG.info("4 Tache de propagation 
> > >>>> key="+taskInfo.getKey());
> > >>>>           }
> > >>>>           PropagationReporter propagationReporter =
> > >>>> taskExecutor.execute(taskInfos, nullPriorityAsync, creator);
> > >>>>           return new ProvisioningResult<>(created.getResult(),
> > >>>> propagationReporter.getStatuses());
> > >>>>       }
> > >>>>
> > >>>>       @Transactional(propagation = Propagation.REQUIRES_NEW)
> > >>>>       @Override
> > >>>>       public List<PropagationStatus> delete(
> > >>>>               final String key,
> > >>>>               final Set<String> excludedResources,
> > >>>>               final boolean nullPriorityAsync,
> > >>>>               final String eraser,
> > >>>>               final String context) {
> > >>>>
> > >>>>           LOG.info("1 Suppression un objet clé="+key);
> > >>>>           Optional<? extends AnyObject> anyObject = 
> > >>>> anyObjectDAO.findById(key);
> > >>>>           boolean objDel = false;
> > >>>>           if(anyObject.isEmpty() || !anyObject.isPresent()){
> > >>>>               LOG.warn("Pas retrouvé l'objet clé="+key);
> > >>>>           }else{
> > >>>>               LOG.info("2 Suppression un objet 
> > >>>> type="+anyObject.get().getType()+
> > >>>>                       " avec name="+anyObject.get().getName());
> > >>>>               objDel = true;
> > >>>>           }
> > >>>>           if(objDel &&
> > >>>> anyObject.get().getType().toString().equals("JPAAnyType[PERSON]")){
> > >>>>               LOG.info("3 Suppression un objet PERSON dans 
> > >>>> provisioning name="+
> > >>>>                       anyObject.get().getName()+" key="+key);
> > >>>>               List<User> users = null;
> > >>>>               boolean erreur = false;
> > >>>>               try{
> > >>>>                   users = userDAO.findByDerAttrValue("personName==",
> > >>>> anyObject.get().getName(), false);
> > >>>>               }catch(Exception ex){
> > >>>>                   LOG.error("Erreur recherche USER "+ex);
> > >>>>                   erreur = true;
> > >>>>               }
> > >>>>               if(!erreur && users != null && !users.isEmpty()){
> > >>>>                   //on trouve un des comptes
> > >>>>                   LOG.info("4 Trouver des comptes, on flingue");
> > >>>>                   for(User user : users){
> > >>>>                       userDAO.delete(user);
> > >>>>                   }
> > >>>>               }
> > >>>>           }
> > >>>>           PropagationByResource<String> propByRes = new 
> > >>>> PropagationByResource<>();
> > >>>>           propByRes.set(ResourceOperation.DELETE,
> > >>>> anyObjectDAO.findAllResourceKeys(key));
> > >>>>
> > >>>>           // Note here that we can only notify about "delete", not any 
> > >>>> other
> > >>>>           // task defined in workflow process definition: this because 
> > >>>> this
> > >>>>           // information could only be available after 
> > >>>> awfAdapter.delete(), which
> > >>>>           // will also effectively remove user from db, thus making 
> > >>>> virtually
> > >>>>           // impossible by NotificationManager to fetch required any
> > >>>> object information
> > >>>>      //En gros les informations / objet produits dans le workflow sont
> > >>>> inaccessibles car il va supprimer l'objet
> > >>>>      //donc seuls les "ressources liées" sont prévenues
> > >>>>           List<PropagationTaskInfo> taskInfos = 
> > >>>> propagationManager.getDeleteTasks(
> > >>>>                   AnyTypeKind.ANY_OBJECT,
> > >>>>                   key,
> > >>>>                   propByRes,
> > >>>>                   null,
> > >>>>                   excludedResources);
> > >>>>           PropagationReporter propagationReporter =
> > >>>> taskExecutor.execute(taskInfos, nullPriorityAsync, eraser);
> > >>>>           awfAdapter.delete(key, eraser, context);
> > >>>>           return propagationReporter.getStatuses();
> > >>>>       }
> > >>>> }
> > >>>>
> > >>>> Le jeu. 8 janv. 2026 à 08:50, Francesco Chicchiriccò
> > >>>> <[email protected]> a écrit :
> > >>>>> Hi,
> > >>>>> my French is not as good as it used to be, so I am not very able to 
> > >>>>> follow :-)
> > >>>>>
> > >>>>> Please try to explain your needs as clear as possible, in English, 
> > >>>>> possibly in terms of requirements.
> > >>>>>
> > >>>>> So far, I have understood that:
> > >>>>>
> > >>>>> 1. you have defined a PERSON AnyType
> > >>>>> 2. you have mapped PERSON to one or more External Resources
> > >>>>> 3. (maybe?) multiple PERSON instances are in Relationship with a 
> > >>>>> single USER instance
> > >>>>> 4. there are events (REST calls to Syncope API? Console 
> > >>>>> modifications?) that are triggering changes on PERSON instances 
> > >>>>> ("arrives first", "change OrganizationalUnit") or possibly the 
> > >>>>> related USER instance; such changes will propagate, through the 
> > >>>>> mapping(s) provided, to the configured External Resource(s)
> > >>>>>
> > >>>>> What I am failing to understand so far:
> > >>>>>
> > >>>>> 1. why you should be modifying the PERSON or USER AnyType definition 
> > >>>>> when the events occurs: I would expect changes to PERSON or USER 
> > >>>>> instances (by adding / removing attributes, memberships or 
> > >>>>> relationships for example) but not the AnyType itself
> > >>>>> 2. whether your are encapsulating somehow the changes (maybe via a 
> > >>>>> custom REST endpoint) which is meant to affect both a USER and 
> > >>>>> related PERSON instance(s)
> > >>>>>
> > >>>>> Maybe you can just provide a couple of examples, using Syncope 
> > >>>>> concepts as AnyType, Relationships, instances, Resources, etc.
> > >>>>>
> > >>>>> Regards.
> > >>>>>
> > >>>>> On 07/01/26 11:30, Stéphane Popoff wrote:
> > >>>>>> Happy new year,
> > >>>>>> About my use case I made a short video
> > >>>>>> [https://sites.google.com/spopoff.net/integrationsyncope/democonnsync?usp=sharing]
> > >>>>>> to explain the need.
> > >>>>>>
> > >>>>>> Best regards,
> > >>>>>> Stéphane POPOFF
> > >>>>>>
> > >>>>>> Le mer. 31 déc. 2025 à 11:27, Stéphane Popoff <[email protected]> 
> > >>>>>> a écrit :
> > >>>>>>> Hi Francesco,
> > >>>>>>> I want to manage access (User account) by an identity object, that 
> > >>>>>>> was supported by an AnyObject PERSON and it's connector. So the 
> > >>>>>>> life cycle of the object PERSON conducts the need of access of the 
> > >>>>>>> identity. In fact PERSON is the the real digital identity, not as 
> > >>>>>>> User in the Syncope's design, and User only supports access.
> > >>>>>>> Hope it's more clear.
> > >>>>>>>
> > >>>>>>> Best regards,
> > >>>>>>> Stéphane popoff
> > >>>>>>>
> > >>>>>>> Le mer. 31 déc. 2025, 07:59, Francesco Chicchiriccò 
> > >>>>>>> <[email protected]> a écrit :
> > >>>>>>>> Hi,
> > >>>>>>>> I am not sure to understand your use case - or better, I am not 
> > >>>>>>>> sure to understand why a change to the USER AnyType should be 
> > >>>>>>>> involved.
> > >>>>>>>>
> > >>>>>>>> Can you please describe what you are trying to achieve from an 
> > >>>>>>>> abstract point of view?
> > >>>>>>>>
> > >>>>>>>> Regards.
> > >>>>>>>>
> > >>>>>>>> On 30/12/25 19:31, Stéphane Popoff wrote:
> > >>>>>>>>> Hello,
> > >>>>>>>>>
> > >>>>>>>>> I have a use case where a flow of objects (JPAAnyType[PERSON]) may
> > >>>>>>>>> produce change on accounts (User).
> > >>>>>>>>> Beside the 2 flows I want to introduce a business logic of kind:
> > >>>>>>>>> - If a person arrive first, we give it a basic access to RH 
> > >>>>>>>>> system and
> > >>>>>>>>> a basic access to the tool of this operationalUnit
> > >>>>>>>>> - If a person changes this operationalUnit, previous access is 
> > >>>>>>>>> closed,
> > >>>>>>>>> newest is open (with or without overlay)
> > >>>>>>>>> - well real time implementation of an IAM system ;-)
> > >>>>>>>>> My question is where can I put this logic ? In the Provisioning
> > >>>>>>>>> Manager or/and/xor in the Workflow ?
> > >>>>>>>>>
> > >>>>>>>>> I did some tests and found that mixing operations across types
> > >>>>>>>>> (JPAAnyType[PERSON] and User) in a basic workflow creates 
> > >>>>>>>>> problems.
> > >>>>>>>>>
> > >>>>>>>>> Best regards, happy new eve,
> > >>>>>>>>> Stéphane POPOFF
> > >
> >
> > --
> > 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