Work in progress!

Following the implementation of the new User API we now need to tackle the Group API too since it's related.


  • Requirement 1: The Group API must be homogeneous with the User API and more specifically it must abide by all its requirements, transposed to groups
  • Requirement 2: Ability to list all groups a user belongs to
  • Requirement 3: A user can belong to several groups
  • Requirement 4: Ability to list all groups
  • Requirement 5: A group can include another group
  • Requirement 6: User properties are not inherited from its groups. It wouldn't make sense since a user can belong to several groups at once. It's up to specific code to decide what to do with it. For example, some feature could check if the user is part of a group having displayHiddenDocuments set to true to decide to display hidden docs or not. Or to display some special actions if the user belongs to a group having an Advanced user type.


There are 4 main options:

  1. Groups are Users: Consider that there's no notion of Group. Everything is a user. Thus there's a single User API. There are some Users who can contain other users (they are Groups).
  2. Groups and Users are Actors: Single API but no more notions of Users or Groups at API level, just Actors. Some Actor can contain other Actors.
  3. Separate Group API: Consider that they are separate concepts and that we have a UserReference and GroupReference and different Resolvers & Serializers, etc.
  4. Separate Group + User + Actor APIs: Same as option 3 but with both a generic API (Actor API) and more specific APIs (User and Group APIs).

Analysis of option 1:

  • Good: Single API
  • Implementation detail: We cannot have Groups implemented as Nested Pages. There's a problem for Requirement 3, as you cannot have a user belonging to several groups not in the same hierarchy. 
  • We need to add UserReference#isGroup() to recognize groups amongst users
  • There are some user properties that don't make much sense for Groups:
    • First name and Last name. This could be solved by using get/setName(Name), have Name#getDisplayName() and have 2 Name implementations (SimpleName and FullName).
    • Default Editor
    • User Type
    • Even though Default Editor and User Type don't make much sense at first sight, they're not a big problem and they could even find use cases for them. At worse they're not used. Note that the email is interesting to represent a mailing list or mail alias for example.
    • If that's problem we could imagine introducing a common class to represent common User and Group properties and when resolving a User return either a UserProperties or a GroupProperties depending if the ref is a user ref or a group reference.
  • Need a way for UserManager#getUserIterator() to return only groups (probably a boolean parameter in one of the signatures)
  • Doesn't work if we want to be able to use different stores for users and groups. This could well be a requirement. Example: imagine in the future someone wants to implement groups with tags (all pages tagged with some tag belong to that group), while keeping users store in wiki pages.

Analysis of option 2:

  • A bit better than option 1 since it's hard to see Groups as Users IMO. 
  • Same problems as option 1 though/

Analysis of option 3:

  • 2 APIs to maintain
  • More clear than option 1 since viewing a Group as a special User is not that obvious
  • We can control the properties more finely
  • More future proof than options 1 or 2. Imagine we find some concepts that only exist in Users or Groups. We're stuck with options 1 and 2.

Analysis of option 4:

  • 3 APIs to maintain
  • Sometimes we need to manipulate Users or Groups without caring whether they're users or groups. The user picks the API to use based on his/her needs
  • Similar to EntityReference and DocumentReference / SpaceReference / WikiReference.
  • The ActorReferencePropertiesResolver would return only common properties between Users and Groups.



Get Connected