5.3. Managing Relationships
Relationships are used to model typed associations between two or more identities. All concrete relationship types must implement the marker interface
org.picketlink.idm.model.Relationship
:
The
RelationshipManager
interface provides three standard methods for managing relationships:
void add(Relationship relationship); void update(Relationship relationship); void remove(Relationship relationship);
-
The
add()
method is used to create a new relationship. -
The
update()
method is used to update an existing relationship.Note
Please note that the identities that participate in a relationship cannot be updated themselves, however the attribute values of the relationship can be updated. If you absolutely need to modify the identities of a relationship, then delete the relationship and create it again. -
The
remove()
method is used to remove an existing relationship. -
The
createRelationshipQuery()
method is used to perform relationship queries. -
The
inheritsPrivileges()
method is used to check whether an identity inherits privileges from another.
Note
To search for existing relationships between identity objects, use the Relationship Query API described later in this chapter.
5.3.1. Built In Relationship Types
PicketLink provides a number of built-in relationship types, designed to address the most common requirements of a typical application. The following sections describe the built-in relationships and how they are intended to be used. Every built-in relationship type extends the
AbstractAttributedType
abstract class, which provides the basic methods for setting a unique identifier value and managing a set of attribute values:

What this means in practical terms, is that every single relationship is assigned and can be identified by, a unique identifier value. Also, arbitrary attribute values may be set for all relationship types, which is useful if you require additional metadata or any other type of information to be stored with a relationship.
5.3.1.1. Application Roles
Application roles are represented by the
Grant
relationship, which is used to assign application-wide privileges to a User
or Agent
.

The
RelationshipManager
interface provides methods for directly granting a role. Here's a simple example:
User bob = BasicModel.getUser(identityManager, "bob"); Role superuser = BasicModel.getRole(identityManager, "superuser"); BasicModel.grantRole(relationshipManager, bob, superuser);
The above code is equivalent to the following:
User bob = BasicModel.getUser(identityManager, "bob"); Role superuser = BasicModel.getRole(identityManager, "superuser"); Grant grant = new Grant(bob, superuser); identityManager.add(grant);
A granted role can also be revoked using the
revokeRole()
method:
User bob = BasicModel.getUser(identityManager, "bob"); Role superuser = BasicModel.getRole(identityManager, "superuser"); BasicModel.revokeRole(relationshipManager, bob, superuser);
To check whether an identity has a specific role granted to them, we can use the
hasRole()
method:
User bob = BasicModel.getUser(identityManager, "bob"); Role superuser = BasicModel.getRole(identityManager, "superuser"); boolean isBobASuperUser = BasicModel.hasRole(relationshipManager, bob, superuser);
5.3.1.2. Groups and Group Roles
The
GroupMembership
and GroupRole
relationships are used to represent a user's membership within a Group
, and a user's role for a group, respectively.

Note
While the
GroupRole
relationship type extends GroupMembership
, it does not mean that a member of a GroupRole
automatically receives GroupMembership
membership also - these are two distinct relationship types with different semantics.
A
Group
is typically used to form logical collections of users. Within an organisation, groups are often used to mirror the organisation's structure. For example, a corporate structure might consist of a sales department, administration, management, etc. This structure can be modelled in PicketLink by creating corresponding groups such as sales, administration, and so forth. Users (who would represent the employees in a corporate structure) may then be assigned group memberships corresponding to their place within the company's organisational structure. For example, an employee who works in the sales department may be assigned to the sales group. Specific application privileges can then be blanket assigned to the sales group, and anyone who is a member of the group is free to access the application's features that require those privileges.
The
GroupRole
relationship type should be used when it is intended for an identity to perform a specific role for a group, but not be an actual member of the group itself. For example, an administrator of a group of doctors may not be a doctor themselves, but have an administrative role to perform for that group. If the intent is for an individual identity to both be a member of a group and have an assigned role in that group also, then the identity should have both GroupRole
and GroupMembership
relationships for that group.
Let's start by looking at a simple example - we'll begin by making the assumption that our organization is structured in the following way:

The following code demonstrates how we would create the hypothetical Sales group which is displayed at the head of the above organisational chart:
Group sales = new Group("Sales"); identityManager.add(sales);
We can then proceed to create its subgroups:
identityManager.add(new Group("North America", sales); identityManager.add(new Group("EMEA", sales); identityManager.add(new Group("Asia", sales); // and so forth
The second parameter of the
Group()
constructor is used to specify the group's parent group. This allows us to create a hierarchical group structure, which can be used to mirror either a simple or complex personnel structure of an organisation. Let's now take a look at how we assign users to these groups.
The following code demonstrates how to assign an administrator group role for the Northeast sales group to user jsmith. The administrator group role may be used to grant certain users the privilege to modify permissions and roles for that group:
Role admin = BasicModel.getRole(identityManager, "administrator"); User user = BasicModel.getUser(identityManager, "jsmith"); Group group = BasicModel.getGroup(identityManager, "Northeast"); BasicModel.grantGroupRole(relationshipManager, user, admin, group);
A group role can be revoked using the
revokeGroupRole()
method:
BasicModel.revokeGroupRole(relationshipManager, user, admin, group);
To test whether a user has a particular group role, you can use the
hasGroupRole()
method:
boolean isUserAGroupAdmin = BasicModel.hasGroupRole(relationshipManager, user, admin, group);
Next, let's look at some examples of how to work with simple group memberships. The following code demonstrates how we assign sales staff rbrown to the Northeast sales group:
User user = BasicModel.getUser(identityManager, "rbrown"); Group group = BasicModel.getGroup(identityManager, "Northeast"); BasicModel.addToGroup(relationshipManager, user, group);
A
User
may also be a member of more than one Group
; there are no built-in limitations on the number of groups that a User
may be a member of.
We can use the
removeFromGroup()
method to remove the same user from the group:
BasicModel.removeFromGroup(relationshipManager, user, group);
To check whether a user is the member of a group we can use the
isMember()
method:
boolean isUserAMember = BasicModel.isMember(relationshipManager, user, group);
Relationships can also be created via the
add()
method. The following code is equivalent to assigning a group role via the grantGroupRole()
method shown above:
Role admin = BasicModel.getRole(identityManager, "administrator"); User user = BasicModel.getUser(identityManager, "jsmith"); Group group = BasicModel.getGroup(identityManager, "Northeast"); GroupRole groupRole = new GroupRole(user, group, admin); identityManager.add(groupRole);