package org.keycloak.testsuite.cli.admin;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.client.admin.cli.config.FileConfigHandler;
import org.keycloak.testsuite.cli.KcAdmExec;
import org.keycloak.testsuite.util.TempFileResource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
import static org.keycloak.testsuite.cli.KcAdmExec.execute;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class KcAdmSessionTest extends AbstractAdmCliTest {
static Class<? extends List<ObjectNode>> LIST_OF_JSON = new ArrayList<ObjectNode>() {}.getClass();
@Test
public void test() throws IOException {
FileConfigHandler handler = initCustomConfigFile();
try (TempFileResource configFile = new TempFileResource(handler.getConfigFile())) {
// login as admin
loginAsUser(configFile.getFile(), serverUrl, "master", "admin", "admin");
// create realm
KcAdmExec exe = execute("create realms --config '" + configFile.getName() + "' -s realm=demorealm -s enabled=true");
assertExitCodeAndStreamSizes(exe, 0, 0, 1);
Assert.assertTrue(exe.stderrLines().get(0).startsWith("Created "));
// create user
exe = execute("create users --config '" + configFile.getName() + "' -r demorealm -s username=testuser -s enabled=true -i");
assertExitCodeAndStreamSizes(exe, 0, 1, 0);
String userId = exe.stdoutLines().get(0);
// add realm admin capabilities to user
exe = execute("add-roles --config '" + configFile.getName() + "' -r demorealm --uusername testuser --cclientid realm-management --rolename realm-admin");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
// set password for the user
exe = execute("set-password --config '" + configFile.getName() + "' -r demorealm --username testuser -p password");
assertExitCodeAndStdErrSize(exe, 0, 0);
// login as testuser
loginAsUser(configFile.getFile(), serverUrl, "demorealm", "testuser", "password");
// get realm roles
exe = execute("get-roles --config '" + configFile.getName() + "'");
assertExitCodeAndStdErrSize(exe, 0, 0);
List<ObjectNode> roles = loadJson(exe.stdout(), LIST_OF_JSON);
Assert.assertTrue("expect two realm roles available", roles.size() == 2);
// create realm role
exe = execute("create roles --config '" + configFile.getName() + "' -s name=testrole -s 'description=Test role' -o");
assertExitCodeAndStdErrSize(exe, 0, 0);
ObjectNode role = loadJson(exe.stdout(), ObjectNode.class);
Assert.assertEquals("testrole", role.get("name").asText());
String roleId = role.get("id").asText();
// get realm roles again
exe = execute("get-roles --config '" + configFile.getName() + "'");
assertExitCodeAndStdErrSize(exe, 0, 0);
roles = loadJson(exe.stdout(), LIST_OF_JSON);
Assert.assertTrue("expect three realm roles available", roles.size() == 3);
// create client
exe = execute("create clients --config '" + configFile.getName() + "' -s clientId=testclient -i");
assertExitCodeAndStreamSizes(exe, 0, 1, 0);
String idOfClient = exe.stdoutLines().get(0);
// create client role
exe = execute("create clients/" + idOfClient + "/roles --config '" + configFile.getName() + "' -s name=clientrole -s 'description=Test client role'");
assertExitCodeAndStreamSizes(exe, 0, 0, 1);
Assert.assertTrue(exe.stderrLines().get(0).startsWith("Created "));
// make sure client role has been created
exe = execute("get-roles --config '" + configFile.getName() + "' --cclientid testclient");
assertExitCodeAndStdErrSize(exe, 0, 0);
roles = loadJson(exe.stdout(), LIST_OF_JSON);
Assert.assertTrue("expect one role", roles.size() == 1);
Assert.assertEquals("clientrole", roles.get(0).get("name").asText());
// add created role to user - we are realm admin so we can add role to ourself
exe = execute("add-roles --config '" + configFile.getName() + "' --uusername testuser --cclientid testclient --rolename clientrole");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
// make sure the roles have been added
exe = execute("get-roles --config '" + configFile.getName() + "' --uusername testuser --all");
assertExitCodeAndStdErrSize(exe, 0, 0);
ObjectNode node = loadJson(exe.stdout(), ObjectNode.class);
Assert.assertNotNull(node.get("realmMappings"));
List<String> realmMappings = StreamSupport.stream(node.get("realmMappings").spliterator(), false)
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("offline_access", "uma_authorization"), realmMappings);
ObjectNode clientRoles = (ObjectNode) node.get("clientMappings");
//List<String> fields = asSortedList(clientRoles.fieldNames());
List<String> fields = StreamSupport.stream(clientRoles.spliterator(), false)
.map(o -> o.get("client").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("account", "realm-management", "testclient"), fields);
realmMappings = StreamSupport.stream(clientRoles.get("account").get("mappings").spliterator(), false)
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("manage-account", "view-profile"), realmMappings);
realmMappings = StreamSupport.stream(clientRoles.get("realm-management").get("mappings").spliterator(), false)
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("realm-admin"), realmMappings);
realmMappings = StreamSupport.stream(clientRoles.get("testclient").get("mappings").spliterator(), false)
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("clientrole"), realmMappings);
// add a realm role to the user
exe = execute("add-roles --config '" + configFile.getName() + "' --uusername testuser --rolename testrole");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
// get all roles for the user again
exe = execute("get-roles --config '" + configFile.getName() + "' --uusername testuser --all");
assertExitCodeAndStdErrSize(exe, 0, 0);
node = loadJson(exe.stdout(), ObjectNode.class);
Assert.assertNotNull(node.get("realmMappings"));
realmMappings = StreamSupport.stream(node.get("realmMappings").spliterator(), false)
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
Assert.assertEquals(Arrays.asList("offline_access", "testrole", "uma_authorization"), realmMappings);
// create a group
exe = execute("create groups --config '" + configFile.getName() + "' -s name=TestUsers -i");
assertExitCodeAndStdErrSize(exe, 0, 0);
String groupId = exe.stdoutLines().get(0);
// create a sub-group
exe = execute("create groups/" + groupId + "/children --config '" + configFile.getName() + "' -s name=TestPowerUsers -i");
assertExitCodeAndStdErrSize(exe, 0, 0);
String subGroupId = exe.stdoutLines().get(0);
// add testuser to TestPowerUsers
exe = execute("update users/" + userId + "/groups/" + subGroupId + " --config '" + configFile.getName()
+ "' -s realm=demorealm -s userId=" + userId + " -s groupId=" + subGroupId + " -n");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
// delete everything
exe = execute("delete groups/" + subGroupId + " --config '" + configFile.getName() + "'");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
exe = execute("delete groups/" + groupId + " --config '" + configFile.getName() + "'");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
exe = execute("delete clients/" + idOfClient + " --config '" + configFile.getName() + "'");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
exe = execute("delete roles/testrole --config '" + configFile.getName() + "'");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
exe = execute("delete users/" + userId + " --config '" + configFile.getName() + "'");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
// delete realm as well - using initial master realm session still saved in config file
exe = execute("delete realms/demorealm --config '" + configFile.getName() + "' --realm master");
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
}
}
}