Merge pull request #1928 from stianst/master
KEYCLOAK-2176 Add default roles and actions to users created with add…
This commit is contained in:
commit
73cf2404ff
4 changed files with 136 additions and 52 deletions
|
@ -1044,35 +1044,14 @@ public class RepresentationToModel {
|
||||||
user.addRequiredAction(UserModel.RequiredAction.valueOf(requiredAction));
|
user.addRequiredAction(UserModel.RequiredAction.valueOf(requiredAction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (userRep.getCredentials() != null) {
|
createCredentials(userRep, user);
|
||||||
for (CredentialRepresentation cred : userRep.getCredentials()) {
|
|
||||||
updateCredential(user, cred);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (userRep.getFederatedIdentities() != null) {
|
if (userRep.getFederatedIdentities() != null) {
|
||||||
for (FederatedIdentityRepresentation identity : userRep.getFederatedIdentities()) {
|
for (FederatedIdentityRepresentation identity : userRep.getFederatedIdentities()) {
|
||||||
FederatedIdentityModel mappingModel = new FederatedIdentityModel(identity.getIdentityProvider(), identity.getUserId(), identity.getUserName());
|
FederatedIdentityModel mappingModel = new FederatedIdentityModel(identity.getIdentityProvider(), identity.getUserId(), identity.getUserName());
|
||||||
session.users().addFederatedIdentity(newRealm, user, mappingModel);
|
session.users().addFederatedIdentity(newRealm, user, mappingModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (userRep.getRealmRoles() != null) {
|
createRoleMappings(userRep, user, newRealm);
|
||||||
for (String roleString : userRep.getRealmRoles()) {
|
|
||||||
RoleModel role = newRealm.getRole(roleString.trim());
|
|
||||||
if (role == null) {
|
|
||||||
role = newRealm.addRole(roleString.trim());
|
|
||||||
}
|
|
||||||
user.grantRole(role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (userRep.getClientRoles() != null) {
|
|
||||||
for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
|
|
||||||
ClientModel client = clientMap.get(entry.getKey());
|
|
||||||
if (client == null) {
|
|
||||||
throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
|
|
||||||
}
|
|
||||||
createClientRoleMappings(client, user, entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (userRep.getClientConsents() != null) {
|
if (userRep.getClientConsents() != null) {
|
||||||
for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
|
for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
|
||||||
UserConsentModel consentModel = toModel(newRealm, consentRep);
|
UserConsentModel consentModel = toModel(newRealm, consentRep);
|
||||||
|
@ -1100,6 +1079,14 @@ public class RepresentationToModel {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void createCredentials(UserRepresentation userRep, UserModel user) {
|
||||||
|
if (userRep.getCredentials() != null) {
|
||||||
|
for (CredentialRepresentation cred : userRep.getCredentials()) {
|
||||||
|
updateCredential(user, cred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Detect if it is "plain-text" or "hashed" representation and update model according to it
|
// Detect if it is "plain-text" or "hashed" representation and update model according to it
|
||||||
private static void updateCredential(UserModel user, CredentialRepresentation cred) {
|
private static void updateCredential(UserModel user, CredentialRepresentation cred) {
|
||||||
if (cred.getValue() != null) {
|
if (cred.getValue() != null) {
|
||||||
|
@ -1142,6 +1129,28 @@ public class RepresentationToModel {
|
||||||
|
|
||||||
// Role mappings
|
// Role mappings
|
||||||
|
|
||||||
|
public static void createRoleMappings(UserRepresentation userRep, UserModel user, RealmModel realm) {
|
||||||
|
if (userRep.getRealmRoles() != null) {
|
||||||
|
for (String roleString : userRep.getRealmRoles()) {
|
||||||
|
RoleModel role = realm.getRole(roleString.trim());
|
||||||
|
if (role == null) {
|
||||||
|
role = realm.addRole(roleString.trim());
|
||||||
|
}
|
||||||
|
user.grantRole(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (userRep.getClientRoles() != null) {
|
||||||
|
Map<String, ClientModel> clientMap = realm.getClientNameMap();
|
||||||
|
for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
|
||||||
|
ClientModel client = clientMap.get(entry.getKey());
|
||||||
|
if (client == null) {
|
||||||
|
throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
|
||||||
|
}
|
||||||
|
createClientRoleMappings(client, user, entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List<String> roleNames) {
|
public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List<String> roleNames) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new RuntimeException("User not found");
|
throw new RuntimeException("User not found");
|
||||||
|
|
|
@ -9,10 +9,7 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.exportimport.ExportImportManager;
|
import org.keycloak.exportimport.ExportImportManager;
|
||||||
import org.keycloak.migration.MigrationModelManager;
|
import org.keycloak.migration.MigrationModelManager;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.*;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.utils.PostMigrationEvent;
|
import org.keycloak.models.utils.PostMigrationEvent;
|
||||||
import org.keycloak.models.utils.RepresentationToModel;
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
@ -263,35 +260,49 @@ public class KeycloakApplication extends Application {
|
||||||
if (addUserFile.isFile()) {
|
if (addUserFile.isFile()) {
|
||||||
log.info("Importing users from '" + addUserFile + "'");
|
log.info("Importing users from '" + addUserFile + "'");
|
||||||
|
|
||||||
|
List<RealmRepresentation> realms;
|
||||||
|
try {
|
||||||
|
realms = JsonSerialization.readValue(new FileInputStream(addUserFile), new TypeReference<List<RealmRepresentation>>() {
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.errorv("Failed to load 'keycloak-add-user.json': {0}", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RealmRepresentation realmRep : realms) {
|
||||||
|
for (UserRepresentation userRep : realmRep.getUsers()) {
|
||||||
KeycloakSession session = sessionFactory.create();
|
KeycloakSession session = sessionFactory.create();
|
||||||
try {
|
try {
|
||||||
session.getTransaction().begin();
|
session.getTransaction().begin();
|
||||||
|
|
||||||
List<RealmRepresentation> realms = JsonSerialization.readValue(new FileInputStream(addUserFile), new TypeReference<List<RealmRepresentation>>() {});
|
RealmModel realm = session.realms().getRealmByName(realmRep.getRealm());
|
||||||
for (RealmRepresentation r : realms) {
|
|
||||||
RealmModel realm = session.realms().getRealmByName(r.getRealm());
|
|
||||||
if (realm == null) {
|
if (realm == null) {
|
||||||
throw new Exception("Realm '" + r.getRealm() + "' not found");
|
log.errorv("Failed to add user ''{0}'' to realm ''{1}'': realm not found", userRep.getUsername(), realmRep.getRealm());
|
||||||
}
|
} else {
|
||||||
|
UserModel user = session.users().addUser(realm, userRep.getUsername());
|
||||||
for (UserRepresentation u : r.getUsers()) {
|
user.setEnabled(userRep.isEnabled());
|
||||||
RepresentationToModel.createUser(session, realm, u, realm.getClientNameMap());
|
RepresentationToModel.createCredentials(userRep, user);
|
||||||
}
|
RepresentationToModel.createRoleMappings(userRep, user, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
session.getTransaction().commit();
|
session.getTransaction().commit();
|
||||||
|
log.infov("Added user ''{0}'' to realm ''{1}''", userRep.getUsername(), realmRep.getRealm());
|
||||||
if (!addUserFile.delete()) {
|
} catch (ModelDuplicateException e) {
|
||||||
log.error("Failed to delete '" + addUserFile + "'");
|
log.errorv("Failed to add user ''{0}'' to realm ''{1}'': user with username exists", userRep.getUsername(), realmRep.getRealm());
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
session.getTransaction().rollback();
|
session.getTransaction().rollback();
|
||||||
log.error("Failed to import users from '" + addUserFile + "'", t);
|
log.errorv("Failed to add user ''{0}'' to realm ''{1}'': {2}", userRep.getUsername(), realmRep.getRealm(), t.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!addUserFile.delete()) {
|
||||||
|
log.errorv("Failed to delete '{0}'", addUserFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T loadJson(InputStream is, Class<T> type) {
|
private static <T> T loadJson(InputStream is, Class<T> type) {
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
package org.keycloak.testsuite.adduser;
|
package org.keycloak.testsuite.adduser;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.type.TypeReference;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
|
import org.keycloak.admin.client.resource.RoleMappingResource;
|
||||||
|
import org.keycloak.admin.client.resource.RoleScopeResource;
|
||||||
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
|
import org.keycloak.common.util.Base64Url;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
||||||
|
import org.keycloak.representations.idm.*;
|
||||||
import org.keycloak.testsuite.KeycloakServer;
|
import org.keycloak.testsuite.KeycloakServer;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.wildfly.adduser.AddUser;
|
import org.keycloak.wildfly.adduser.AddUser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
@ -37,7 +50,16 @@ public class AddUserTest {
|
||||||
@Test
|
@Test
|
||||||
public void addUserTest() throws Throwable {
|
public void addUserTest() throws Throwable {
|
||||||
AddUser.main(new String[]{"-u", "addusertest-admin", "-p", "password"});
|
AddUser.main(new String[]{"-u", "addusertest-admin", "-p", "password"});
|
||||||
Assert.assertEquals(1, dir.listFiles().length);
|
assertEquals(1, dir.listFiles().length);
|
||||||
|
|
||||||
|
List<RealmRepresentation> realms = JsonSerialization.readValue(new FileInputStream(new File(dir, "keycloak-add-user.json")), new TypeReference<List<RealmRepresentation>>() {});
|
||||||
|
assertEquals(1, realms.size());
|
||||||
|
assertEquals(1, realms.get(0).getUsers().size());
|
||||||
|
|
||||||
|
UserRepresentation user = realms.get(0).getUsers().get(0);
|
||||||
|
assertEquals(new Integer(100000), user.getCredentials().get(0).getHashIterations());
|
||||||
|
assertNull(user.getCredentials().get(0).getValue());
|
||||||
|
assertEquals(new Pbkdf2PasswordEncoder(Base64Url.decode(user.getCredentials().get(0).getSalt()), 100000).encode("password"), user.getCredentials().get(0).getHashedSaltedValue());
|
||||||
|
|
||||||
KeycloakServer server = new KeycloakServer();
|
KeycloakServer server = new KeycloakServer();
|
||||||
try {
|
try {
|
||||||
|
@ -53,12 +75,54 @@ public class AddUserTest {
|
||||||
|
|
||||||
keycloak.realms().create(testRealm);
|
keycloak.realms().create(testRealm);
|
||||||
|
|
||||||
|
RealmResource realm = keycloak.realm("master");
|
||||||
|
|
||||||
|
List<UserRepresentation> users = realm.users().search("addusertest-admin", null, null, null, null, null);
|
||||||
|
assertEquals(1, users.size());
|
||||||
|
|
||||||
|
UserRepresentation created = users.get(0);
|
||||||
|
assertNotNull(created.getCreatedTimestamp());
|
||||||
|
|
||||||
|
UserResource userResource = realm.users().get(created.getId());
|
||||||
|
|
||||||
|
List<RoleRepresentation> realmRoles = userResource.roles().realmLevel().listAll();
|
||||||
|
|
||||||
|
assertRoles(realmRoles, "admin", "offline_access");
|
||||||
|
|
||||||
|
List<ClientRepresentation> clients = realm.clients().findAll();
|
||||||
|
String accountId = null;
|
||||||
|
for (ClientRepresentation c : clients) {
|
||||||
|
if (c.getClientId().equals("account")) {
|
||||||
|
accountId = c.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RoleRepresentation> accountRoles = userResource.roles().clientLevel(accountId).listAll();
|
||||||
|
|
||||||
|
assertRoles(accountRoles, "view-profile", "manage-account");
|
||||||
|
|
||||||
keycloak.close();
|
keycloak.close();
|
||||||
|
|
||||||
Assert.assertEquals(0, dir.listFiles().length);
|
assertEquals(0, dir.listFiles().length);
|
||||||
} finally {
|
} finally {
|
||||||
server.stop();
|
server.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void assertRoles(List<RoleRepresentation> actual, String... expected) {
|
||||||
|
assertEquals(expected.length, actual.size());
|
||||||
|
|
||||||
|
for (String e : expected) {
|
||||||
|
boolean found = false;
|
||||||
|
for (RoleRepresentation r : actual) {
|
||||||
|
if (r.getName().equals(e)) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
fail("Role " + e + " not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,9 +154,9 @@ public class AddUser {
|
||||||
roles = rolesString.split(",");
|
roles = rolesString.split(",");
|
||||||
} else {
|
} else {
|
||||||
if (realmName.equals("master")) {
|
if (realmName.equals("master")) {
|
||||||
roles = new String[] { "admin", "account/manage-account" };
|
roles = new String[] { "admin" };
|
||||||
} else {
|
} else {
|
||||||
roles = new String[] { "realm-management/realm-admin", "account/manage-account" };
|
roles = new String[] { "realm-management/realm-admin" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue