190 lines
8.8 KiB
Java
190 lines
8.8 KiB
Java
/*
|
|
* This file is part of Player Analytics (Plan).
|
|
*
|
|
* Plan is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Plan is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.djrapitops.plan.commands.subcommands;
|
|
|
|
import com.djrapitops.plan.PlanSystem;
|
|
import com.djrapitops.plan.commands.PlanCommand;
|
|
import com.djrapitops.plan.commands.use.Arguments;
|
|
import com.djrapitops.plan.commands.use.CMDSender;
|
|
import com.djrapitops.plan.commands.use.CommandWithSubcommands;
|
|
import com.djrapitops.plan.delivery.domain.auth.User;
|
|
import com.djrapitops.plan.delivery.webserver.Addresses;
|
|
import com.djrapitops.plan.settings.Permissions;
|
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
|
import com.djrapitops.plan.settings.config.changes.ConfigUpdater;
|
|
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
|
import com.djrapitops.plan.storage.database.Database;
|
|
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
|
|
import com.djrapitops.plan.storage.database.transactions.commands.StoreWebUserTransaction;
|
|
import com.djrapitops.plan.utilities.PassEncryptUtil;
|
|
import com.google.gson.Gson;
|
|
import extension.FullSystemExtension;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.junit.jupiter.api.AfterAll;
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.api.DisplayName;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
import org.junit.jupiter.api.io.TempDir;
|
|
import org.openqa.selenium.json.TypeToken;
|
|
import utilities.HTTPConnector;
|
|
import utilities.TestConstants;
|
|
import utilities.TestResources;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardCopyOption;
|
|
import java.security.KeyManagementException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
/**
|
|
* @author AuroraLS3
|
|
*/
|
|
@ExtendWith(FullSystemExtension.class)
|
|
class RegistrationCommandsTest {
|
|
|
|
@BeforeAll
|
|
static void beforeAll(@TempDir Path tempDir, PlanSystem system) throws Exception {
|
|
File file = tempDir.resolve("TestCert.p12").toFile();
|
|
File testCert = TestResources.getTestResourceFile("TestCert.p12", ConfigUpdater.class);
|
|
Files.copy(testCert.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
String absolutePath = file.getAbsolutePath();
|
|
|
|
PlanConfig config = system.getConfigSystem().getConfig();
|
|
config.set(WebserverSettings.CERTIFICATE_PATH, absolutePath);
|
|
config.set(WebserverSettings.CERTIFICATE_KEYPASS, "test");
|
|
config.set(WebserverSettings.CERTIFICATE_STOREPASS, "test");
|
|
config.set(WebserverSettings.CERTIFICATE_ALIAS, "test");
|
|
|
|
system.enable();
|
|
}
|
|
|
|
@AfterAll
|
|
static void afterAll(PlanSystem system) {
|
|
system.disable();
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("User is registered with 'admin' group with 'plan.webgroup.admin' permission")
|
|
void normalRegistrationFlow(Addresses addresses, PlanCommand command, Database database) throws Exception {
|
|
String username = "normalRegistrationFlow";
|
|
String code = registerUser(username, addresses);
|
|
|
|
CMDSender sender = mock(CMDSender.class);
|
|
when(sender.isPlayer()).thenReturn(true);
|
|
when(sender.hasPermission(Permissions.REGISTER_SELF.getPermission())).thenReturn(true);
|
|
when(sender.hasPermission("plan.webgroup.admin")).thenReturn(true);
|
|
when(sender.getUUID()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_UUID));
|
|
when(sender.getPlayerName()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_NAME));
|
|
|
|
command.build().executeCommand(sender, new Arguments(List.of("register", "--code", code)));
|
|
|
|
User user = database.query(WebUserQueries.fetchUser(username)).orElseThrow(AssertionError::new);
|
|
assertEquals("admin", user.getPermissionGroup());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("User registration fails without any plan.webgroup.{name} permission.")
|
|
void noPermissionFlow(Addresses addresses, PlanCommand command, Database database) throws Exception {
|
|
String username = "noPermissionFlow";
|
|
String code = registerUser(username, addresses);
|
|
|
|
CMDSender sender = mock(CMDSender.class);
|
|
when(sender.isPlayer()).thenReturn(true);
|
|
when(sender.hasPermission(Permissions.REGISTER_SELF.getPermission())).thenReturn(true);
|
|
when(sender.getUUID()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_UUID));
|
|
when(sender.getPlayerName()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_NAME));
|
|
|
|
CommandWithSubcommands cmd = command.build();
|
|
Arguments arguments = new Arguments(List.of("register", "--code", code));
|
|
assertThrows(IllegalArgumentException.class, () -> cmd.executeCommand(sender, arguments));
|
|
|
|
assertTrue(database.query(WebUserQueries.fetchUser(username)).isEmpty());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("User registration fails without any plan.webgroup.{name} permission attempting to bypass.")
|
|
void noPermissionFlowBypassAttempt(Addresses addresses, PlanCommand command, Database database) throws Exception {
|
|
String username = "noPermissionFlowBypassAttempt";
|
|
String code = registerUser(username, addresses);
|
|
|
|
CMDSender sender = mock(CMDSender.class);
|
|
when(sender.isPlayer()).thenReturn(true);
|
|
when(sender.hasPermission(Permissions.REGISTER_SELF.getPermission())).thenReturn(true);
|
|
when(sender.getUUID()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_UUID));
|
|
when(sender.getPlayerName()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_NAME));
|
|
|
|
CommandWithSubcommands cmd = command.build();
|
|
Arguments arguments = new Arguments(List.of("register", "--code", code, "superuser"));
|
|
assertThrows(IllegalArgumentException.class, () -> cmd.executeCommand(sender, arguments));
|
|
|
|
assertTrue(database.query(WebUserQueries.fetchUser(username)).isEmpty());
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("User group is changed")
|
|
void setGroupCommandTest(PlanCommand command, Database database) throws Exception {
|
|
String username = "setGroupCommandTest";
|
|
User user = new User(username, "console", null, PassEncryptUtil.createHash("testPass"), "admin", Collections.emptyList());
|
|
database.executeTransaction(new StoreWebUserTransaction(user)).get();
|
|
|
|
CMDSender sender = mock(CMDSender.class);
|
|
when(sender.isPlayer()).thenReturn(true);
|
|
when(sender.hasPermission(Permissions.SET_GROUP.getPermission())).thenReturn(true);
|
|
when(sender.getUUID()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_UUID));
|
|
when(sender.getPlayerName()).thenReturn(Optional.of(TestConstants.PLAYER_ONE_NAME));
|
|
|
|
command.build().executeCommand(sender, new Arguments(List.of("setgroup", username, "no_access")));
|
|
|
|
User modifiedUser = database.query(WebUserQueries.fetchUser(username)).orElseThrow(AssertionError::new);
|
|
assertEquals("no_access", modifiedUser.getPermissionGroup());
|
|
}
|
|
|
|
private static String registerUser(String username, Addresses addresses) throws IOException, KeyManagementException, NoSuchAlgorithmException {
|
|
HTTPConnector connector = new HTTPConnector();
|
|
HttpURLConnection connection = null;
|
|
String code;
|
|
try {
|
|
String address = addresses.getFallbackLocalhostAddress();
|
|
connection = connector.getConnection("POST", address + "/auth/register");
|
|
connection.setDoOutput(true);
|
|
connection.getOutputStream().write(("user=" + username + "&password=testPass").getBytes());
|
|
try (InputStream in = connection.getInputStream()) {
|
|
String responseBody = new String(IOUtils.toByteArray(in));
|
|
assertTrue(responseBody.contains("\"code\":"), () -> "Not successful: " + responseBody);
|
|
Map<String, Object> read = new Gson().fromJson(responseBody, new TypeToken<Map<String, Object>>() {}.getType());
|
|
code = (String) read.get("code");
|
|
System.out.println("Got registration code: " + code);
|
|
}
|
|
} finally {
|
|
if (connection != null) connection.disconnect();
|
|
}
|
|
return code;
|
|
}
|
|
} |