use of org.keycloak.models.GroupModel in project keycloak by keycloak.
the class UserModelTest method testAddDirtyRemoveFederationUsersInTheSameGroupConcurrent.
@Test
@RequireProvider(UserStorageProvider.class)
public void testAddDirtyRemoveFederationUsersInTheSameGroupConcurrent() {
final ConcurrentSkipListSet<String> userIds = new ConcurrentSkipListSet<>();
String groupId = groupIds.get(0);
registerUserFederationWithRealm();
// Create users and let them join first group
IntStream.range(0, 100).parallel().forEach(index -> inComittedTransaction(index, (session, i) -> {
final RealmModel realm = session.realms().getRealm(realmId);
final UserModel user = session.users().addUser(realm, "user-" + i);
user.joinGroup(session.groups().getGroupById(realm, groupId));
log.infof("Created user with id: %s", user.getId());
userIds.add(user.getId());
return null;
}));
// Remove users _from the federation_, simulates eg. user being removed from LDAP without Keycloak knowing
withRealm(realmId, (session, realm) -> {
UserStorageProvider instance = getUserFederationInstance(session, realm);
log.debugf("Removing selected users from backend");
IntStream.range(FIRST_DELETED_USER_INDEX, LAST_DELETED_USER_INDEX).forEach(j -> {
final UserModel user = session.users().getUserByUsername(realm, "user-" + j);
((UserRegistrationProvider) instance).removeUser(realm, user);
});
return null;
});
IntStream.range(0, 7).parallel().forEach(index -> withRealm(realmId, (session, realm) -> {
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).count(), is(100L - DELETED_USER_COUNT));
return null;
}));
inComittedTransaction(session -> {
// the cache manually.
if (session.userCache() != null) {
session.userCache().clear();
}
return null;
});
// Now delete the users, and count those that were not found to be deleted. This should be equal to the number
// of users removed directly in the user federation.
// Some of the transactions may fail due to conflicts as there are many parallel request, so repeat until all users are removed
AtomicInteger notFoundUsers = new AtomicInteger();
Set<String> remainingUserIds = new HashSet<>();
do {
userIds.stream().parallel().forEach(index -> inComittedTransaction(index, (session, userId) -> {
final RealmModel realm = session.realms().getRealm(realmId);
final UserModel user = session.users().getUserById(realm, userId);
if (user != null) {
log.debugf("Deleting user: %s", userId);
session.users().removeUser(realm, user);
} else {
log.debugf("Failed deleting user: %s", userId);
notFoundUsers.incrementAndGet();
}
return null;
}, null, (session, userId) -> {
log.debugf("Could not delete user %s", userId);
remainingUserIds.add(userId);
}));
userIds.clear();
userIds.addAll(remainingUserIds);
remainingUserIds.clear();
} while (!userIds.isEmpty());
assertThat(notFoundUsers.get(), is(DELETED_USER_COUNT));
withRealm(realmId, (session, realm) -> {
final GroupModel group = session.groups().getGroupById(realm, groupId);
assertThat(session.users().getGroupMembersStream(realm, group).collect(Collectors.toList()), Matchers.empty());
return null;
});
}
use of org.keycloak.models.GroupModel in project keycloak by keycloak.
the class GroupPolicyProviderFactory method onExport.
@Override
public void onExport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
Map<String, String> config = new HashMap<>();
GroupPolicyRepresentation groupPolicy = toRepresentation(policy, authorization);
Set<GroupPolicyRepresentation.GroupDefinition> groups = groupPolicy.getGroups();
for (GroupPolicyRepresentation.GroupDefinition definition : groups) {
GroupModel group = authorization.getRealm().getGroupById(definition.getId());
definition.setId(null);
definition.setPath(ModelToRepresentation.buildGroupPath(group));
}
try {
String groupsClaim = groupPolicy.getGroupsClaim();
if (groupsClaim != null) {
config.put("groupsClaim", groupsClaim);
}
config.put("groups", JsonSerialization.writeValueAsString(groups));
} catch (IOException cause) {
throw new RuntimeException("Failed to export group policy [" + policy.getName() + "]", cause);
}
representation.setConfig(config);
}
use of org.keycloak.models.GroupModel in project keycloak by keycloak.
the class GroupPolicyProviderFactory method updatePolicy.
private void updatePolicy(Policy policy, String groupsClaim, Set<GroupPolicyRepresentation.GroupDefinition> groups, AuthorizationProvider authorization) {
if (groups == null || groups.isEmpty()) {
throw new RuntimeException("You must provide at least one group");
}
Map<String, String> config = new HashMap<>(policy.getConfig());
if (groupsClaim != null) {
config.put("groupsClaim", groupsClaim);
}
List<GroupModel> topLevelGroups = authorization.getRealm().getTopLevelGroupsStream().collect(Collectors.toList());
for (GroupPolicyRepresentation.GroupDefinition definition : groups) {
GroupModel group = null;
if (definition.getId() != null) {
group = authorization.getRealm().getGroupById(definition.getId());
}
String path = definition.getPath();
if (group == null && path != null) {
String canonicalPath = path.startsWith("/") ? path.substring(1, path.length()) : path;
if (canonicalPath != null) {
String[] parts = canonicalPath.split("/");
GroupModel parent = null;
for (String part : parts) {
if (parent == null) {
parent = topLevelGroups.stream().filter(groupModel -> groupModel.getName().equals(part)).findFirst().orElseThrow(() -> new RuntimeException("Top level group with name [" + part + "] not found"));
} else {
group = parent.getSubGroupsStream().filter(groupModel -> groupModel.getName().equals(part)).findFirst().orElseThrow(() -> new RuntimeException("Group with name [" + part + "] not found"));
parent = group;
}
}
if (parts.length == 1) {
group = parent;
}
}
}
if (group == null) {
throw new RuntimeException("Group with id [" + definition.getId() + "] not found");
}
definition.setId(group.getId());
definition.setPath(null);
}
try {
config.put("groups", JsonSerialization.writeValueAsString(groups));
} catch (IOException cause) {
throw new RuntimeException("Failed to serialize groups", cause);
}
policy.setConfig(config);
}
use of org.keycloak.models.GroupModel in project keycloak by keycloak.
the class GroupPolicyProvider method evaluate.
@Override
public void evaluate(Evaluation evaluation) {
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
GroupPolicyRepresentation policy = representationFunction.apply(evaluation.getPolicy(), authorizationProvider);
RealmModel realm = authorizationProvider.getRealm();
Attributes.Entry groupsClaim = evaluation.getContext().getIdentity().getAttributes().getValue(policy.getGroupsClaim());
if (groupsClaim == null || groupsClaim.isEmpty()) {
List<String> userGroups = evaluation.getRealm().getUserGroups(evaluation.getContext().getIdentity().getId());
groupsClaim = new Entry(policy.getGroupsClaim(), userGroups);
}
for (GroupPolicyRepresentation.GroupDefinition definition : policy.getGroups()) {
GroupModel allowedGroup = realm.getGroupById(definition.getId());
for (int i = 0; i < groupsClaim.size(); i++) {
String group = groupsClaim.asString(i);
if (group.indexOf('/') != -1) {
String allowedGroupPath = buildGroupPath(allowedGroup);
if (group.equals(allowedGroupPath) || (definition.isExtendChildren() && group.startsWith(allowedGroupPath))) {
evaluation.grant();
return;
}
}
// in case the group from the claim does not represent a path, we just check an exact name match
if (group.equals(allowedGroup.getName())) {
evaluation.grant();
return;
}
}
}
}
use of org.keycloak.models.GroupModel in project keycloak by keycloak.
the class GroupLDAPStorageMapper method onImportUserFromLDAP.
@Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
LDAPGroupMapperMode mode = config.getMode();
// For now, import LDAP group mappings just during create
if (mode == LDAPGroupMapperMode.IMPORT && isCreate) {
List<LDAPObject> ldapGroups = getLDAPGroupMappings(ldapUser);
// Import role mappings from LDAP into Keycloak DB
for (LDAPObject ldapGroup : ldapGroups) {
GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, ldapGroup, user);
if (kcGroup != null) {
logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName());
user.joinGroup(kcGroup);
}
}
}
}
Aggregations