Added Untrusted-annotation to be more careful around user given data

- Fixed SQL-injection vulnerability in an endpoint
- Fixed XSS on Whitelist deny 403 page
- Fixed XSS on Internal Error 500 page if untrusted data ends up in exception message
This commit is contained in:
Aurora Lahtela 2023-01-14 22:17:50 +02:00
parent 82274ae658
commit 38785a9505
90 changed files with 498 additions and 347 deletions

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.addons.placeholderapi;
import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.placeholder.PlanPlaceholders; import com.djrapitops.plan.placeholder.PlanPlaceholders;
import com.djrapitops.plan.processing.Processing; import com.djrapitops.plan.processing.Processing;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import com.djrapitops.plan.version.VersionChecker; import com.djrapitops.plan.version.VersionChecker;
@ -89,7 +90,7 @@ public class PlanPlaceholderExtension extends PlaceholderExpansion {
} }
@Override @Override
public String onRequest(OfflinePlayer player, String params) { public String onRequest(OfflinePlayer player, @Untrusted String params) {
UUID uuid = player != null ? player.getUniqueId() : null; UUID uuid = player != null ? player.getUniqueId() : null;
if ("Server thread".equalsIgnoreCase(Thread.currentThread().getName())) { if ("Server thread".equalsIgnoreCase(Thread.currentThread().getName())) {
return getCached(params, uuid); return getCached(params, uuid);
@ -97,7 +98,7 @@ public class PlanPlaceholderExtension extends PlaceholderExpansion {
return getPlaceholderValue(params, uuid); return getPlaceholderValue(params, uuid);
} }
private String getPlaceholderValue(String params, UUID uuid) { private String getPlaceholderValue(@Untrusted String params, UUID uuid) {
try { try {
String value = placeholders.onPlaceholderRequest(uuid, parseRequest(params), parseParameters(params)); String value = placeholders.onPlaceholderRequest(uuid, parseRequest(params), parseParameters(params));
@ -114,14 +115,16 @@ public class PlanPlaceholderExtension extends PlaceholderExpansion {
} }
} }
private String parseRequest(String params) { @Untrusted
private String parseRequest(@Untrusted String params) {
return params.split(":")[0]; return params.split(":")[0];
} }
private List<String> parseParameters(String params) { @Untrusted
private List<String> parseParameters(@Untrusted String params) {
List<String> parameters = new ArrayList<>(); List<String> parameters = new ArrayList<>();
boolean first = true; boolean first = true;
for (String parameter : params.split(":")) { for (@Untrusted String parameter : params.split(":")) {
if (first) { if (first) {
first = false; first = false;
} else { } else {
@ -131,8 +134,8 @@ public class PlanPlaceholderExtension extends PlaceholderExpansion {
return parameters; return parameters;
} }
private String getCached(String params, UUID uuid) { private String getCached(@Untrusted String params, UUID uuid) {
String key = params + "-" + uuid; @Untrusted String key = params + "-" + uuid;
if (!currentlyProcessing.contains(key)) { if (!currentlyProcessing.contains(key)) {
currentlyProcessing.add(key); currentlyProcessing.add(key);

View File

@ -24,6 +24,7 @@ import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.DeepHelpLang; import com.djrapitops.plan.settings.locale.lang.DeepHelpLang;
import com.djrapitops.plan.settings.locale.lang.HelpLang; import com.djrapitops.plan.settings.locale.lang.HelpLang;
import com.djrapitops.plan.storage.database.DBType; import com.djrapitops.plan.storage.database.DBType;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
@ -84,7 +85,7 @@ public class PlanCommand {
this.errorLogger = errorLogger; this.errorLogger = errorLogger;
} }
private void handleException(RuntimeException error, CMDSender sender, Arguments arguments) { private void handleException(RuntimeException error, CMDSender sender, @Untrusted Arguments arguments) {
if (error instanceof IllegalArgumentException) { if (error instanceof IllegalArgumentException) {
sender.send("§c" + error.getMessage()); sender.send("§c" + error.getMessage());
} else { } else {
@ -131,13 +132,13 @@ public class PlanCommand {
return command; return command;
} }
public List<String> serverNames(CMDSender sender, Arguments arguments) { public List<String> serverNames(CMDSender sender, @Untrusted Arguments arguments) {
String asString = arguments.concatenate(" "); @Untrusted String asString = arguments.concatenate(" ");
return tabCompleteCache.getMatchingServerIdentifiers(asString); return tabCompleteCache.getMatchingServerIdentifiers(asString);
} }
private List<String> playerNames(CMDSender sender, Arguments arguments) { private List<String> playerNames(CMDSender sender, @Untrusted Arguments arguments) {
String asString = arguments.concatenate(" "); @Untrusted String asString = arguments.concatenate(" ");
return tabCompleteCache.getMatchingPlayerIdentifiers(asString); return tabCompleteCache.getMatchingPlayerIdentifiers(asString);
} }
@ -254,12 +255,12 @@ public class PlanCommand {
.build(); .build();
} }
private List<String> webUserNames(CMDSender sender, Arguments arguments) { private List<String> webUserNames(CMDSender sender, @Untrusted Arguments arguments) {
if (!sender.hasPermission(Permissions.UNREGISTER_OTHER)) { if (!sender.hasPermission(Permissions.UNREGISTER_OTHER)) {
return Collections.emptyList(); return Collections.emptyList();
} }
String username = arguments.concatenate(" "); @Untrusted String username = arguments.concatenate(" ");
return tabCompleteCache.getMatchingUserIdentifiers(username); return tabCompleteCache.getMatchingUserIdentifiers(username);
} }
@ -388,15 +389,15 @@ public class PlanCommand {
.build(); .build();
} }
private List<String> getBackupFilenames(CMDSender sender, Arguments arguments) { private List<String> getBackupFilenames(CMDSender sender, @Untrusted Arguments arguments) {
if (arguments.get(1).isPresent()) { if (arguments.get(1).isPresent()) {
return DBType.names(); return DBType.names();
} }
Optional<String> firstArgument = arguments.get(0); @Untrusted Optional<String> firstArgument = arguments.get(0);
if (firstArgument.isEmpty()) { if (firstArgument.isEmpty()) {
return tabCompleteCache.getMatchingBackupFilenames(null); return tabCompleteCache.getMatchingBackupFilenames(null);
} }
String part = firstArgument.get(); @Untrusted String part = firstArgument.get();
return tabCompleteCache.getMatchingBackupFilenames(part); return tabCompleteCache.getMatchingBackupFilenames(part);
} }

View File

@ -27,6 +27,7 @@ import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries; import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.inject.Inject; import javax.inject.Inject;
@ -115,25 +116,25 @@ public class TabCompleteCache implements SubSystem {
backupFileNames.clear(); backupFileNames.clear();
} }
public List<String> getMatchingServerIdentifiers(String searchFor) { public List<String> getMatchingServerIdentifiers(@Untrusted String searchFor) {
return findMatches(serverIdentifiers, searchFor); return findMatches(serverIdentifiers, searchFor);
} }
public List<String> getMatchingPlayerIdentifiers(String searchFor) { public List<String> getMatchingPlayerIdentifiers(@Untrusted String searchFor) {
playerIdentifiers.addAll(serverSensor.getOnlinePlayerNames()); playerIdentifiers.addAll(serverSensor.getOnlinePlayerNames());
return findMatches(playerIdentifiers, searchFor); return findMatches(playerIdentifiers, searchFor);
} }
public List<String> getMatchingUserIdentifiers(String searchFor) { public List<String> getMatchingUserIdentifiers(@Untrusted String searchFor) {
return findMatches(userIdentifiers, searchFor); return findMatches(userIdentifiers, searchFor);
} }
public List<String> getMatchingBackupFilenames(String searchFor) { public List<String> getMatchingBackupFilenames(@Untrusted String searchFor) {
return findMatches(backupFileNames, searchFor); return findMatches(backupFileNames, searchFor);
} }
@NotNull @NotNull
List<String> findMatches(Collection<String> searchList, String searchFor) { List<String> findMatches(Collection<String> searchList, @Untrusted String searchFor) {
List<String> filtered = searchList.stream() List<String> filtered = searchList.stream()
.filter(identifier -> searchFor == null || searchFor.isEmpty() || identifier.startsWith(searchFor)) .filter(identifier -> searchFor == null || searchFor.isEmpty() || identifier.startsWith(searchFor))
.sorted(String.CASE_INSENSITIVE_ORDER) .sorted(String.CASE_INSENSITIVE_ORDER)

View File

@ -46,6 +46,7 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries; import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries; import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -95,8 +96,8 @@ public class DataUtilityCommands {
} }
} }
public void onExport(CMDSender sender, Arguments arguments) { public void onExport(CMDSender sender, @Untrusted Arguments arguments) {
String exportKind = arguments.get(0) @Untrusted String exportKind = arguments.get(0)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_ACCEPTS_ARGUMENTS, locale.getString(HelpLang.ARG_EXPORT_KIND), "players, server_json"))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_ACCEPTS_ARGUMENTS, locale.getString(HelpLang.ARG_EXPORT_KIND), "players, server_json")));
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
@ -104,7 +105,7 @@ public class DataUtilityCommands {
getExportFunction(exportKind).accept(sender); getExportFunction(exportKind).accept(sender);
} }
private Consumer<CMDSender> getExportFunction(String exportArg) { private Consumer<CMDSender> getExportFunction(@Untrusted String exportArg) {
if ("players".equals(exportArg)) { if ("players".equals(exportArg)) {
return this::exportPlayers; return this::exportPlayers;
} else if ("server_json".endsWith(exportArg)) { } else if ("server_json".endsWith(exportArg)) {
@ -176,8 +177,8 @@ public class DataUtilityCommands {
} }
} }
public void onImport(CMDSender sender, Arguments arguments) { public void onImport(CMDSender sender, @Untrusted Arguments arguments) {
String importKind = arguments.get(0) @Untrusted String importKind = arguments.get(0)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_ACCEPTS_ARGUMENTS, locale.getString(HelpLang.ARG_IMPORT_KIND), importSystem.getImporterNames().toString()))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_ACCEPTS_ARGUMENTS, locale.getString(HelpLang.ARG_IMPORT_KIND), importSystem.getImporterNames().toString())));
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
@ -185,7 +186,7 @@ public class DataUtilityCommands {
findAndProcessImporter(sender, importKind); findAndProcessImporter(sender, importKind);
} }
private void findAndProcessImporter(CMDSender sender, String importKind) { private void findAndProcessImporter(CMDSender sender, @Untrusted String importKind) {
Optional<Importer> foundImporter = importSystem.getImporter(importKind); Optional<Importer> foundImporter = importSystem.getImporter(importKind);
if (foundImporter.isPresent()) { if (foundImporter.isPresent()) {
Importer importer = foundImporter.get(); Importer importer = foundImporter.get();
@ -199,8 +200,8 @@ public class DataUtilityCommands {
} }
} }
public void onSearch(CMDSender sender, Arguments arguments) { public void onSearch(CMDSender sender, @Untrusted Arguments arguments) {
String searchingFor = arguments.concatenate(" "); @Untrusted String searchingFor = arguments.concatenate(" ");
if (searchingFor.trim().isEmpty()) { if (searchingFor.trim().isEmpty()) {
throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_EMPTY_SEARCH_STRING)); throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_EMPTY_SEARCH_STRING));
} }
@ -221,8 +222,8 @@ public class DataUtilityCommands {
sender.send(sender.getFormatter().table(asTableString.toString(), "::")); sender.send(sender.getFormatter().table(asTableString.toString(), "::"));
} }
public void onInGame(CMDSender sender, Arguments arguments) { public void onInGame(CMDSender sender, @Untrusted Arguments arguments) {
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
UUID playerUUID = identifiers.getPlayerUUID(identifier); UUID playerUUID = identifiers.getPlayerUUID(identifier);
UUID senderUUID = sender.getUUID().orElse(null); UUID senderUUID = sender.getUUID().orElse(null);
if (playerUUID == null) playerUUID = senderUUID; if (playerUUID == null) playerUUID = senderUUID;

View File

@ -46,6 +46,7 @@ import com.djrapitops.plan.storage.database.transactions.Transaction;
import com.djrapitops.plan.storage.database.transactions.commands.*; import com.djrapitops.plan.storage.database.transactions.commands.*;
import com.djrapitops.plan.storage.database.transactions.patches.BadFabricJoinAddressValuePatch; import com.djrapitops.plan.storage.database.transactions.patches.BadFabricJoinAddressValuePatch;
import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import net.playeranalytics.plugin.player.UUIDFetcher; import net.playeranalytics.plugin.player.UUIDFetcher;
@ -113,7 +114,7 @@ public class DatabaseCommands {
this.processing = processing; this.processing = processing;
} }
public void onBackup(CMDSender sender, Arguments arguments) { public void onBackup(CMDSender sender, @Untrusted Arguments arguments) {
String dbName = arguments.get(0) String dbName = arguments.get(0)
.orElse(dbSystem.getDatabase().getType().getName()) .orElse(dbSystem.getDatabase().getType().getName())
.toLowerCase(); .toLowerCase();
@ -129,7 +130,7 @@ public class DatabaseCommands {
sender.send(locale.getString(CommandLang.PROGRESS_SUCCESS)); sender.send(locale.getString(CommandLang.PROGRESS_SUCCESS));
} }
public void performBackup(CMDSender sender, Arguments arguments, String dbName, Database fromDB) { public void performBackup(CMDSender sender, @Untrusted Arguments arguments, String dbName, Database fromDB) {
Database toDB = null; Database toDB = null;
try { try {
String timeStamp = timestamp.apply(System.currentTimeMillis()); String timeStamp = timestamp.apply(System.currentTimeMillis());
@ -150,8 +151,8 @@ public class DatabaseCommands {
} }
} }
public void onRestore(String mainCommand, CMDSender sender, Arguments arguments) { public void onRestore(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
String backupDbName = arguments.get(0) @Untrusted String backupDbName = arguments.get(0)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, "<" + locale.getString(HelpLang.ARG_BACKUP_FILE) + ">"))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, "<" + locale.getString(HelpLang.ARG_BACKUP_FILE) + ">")));
boolean containsDBFileExtension = backupDbName.endsWith(".db"); boolean containsDBFileExtension = backupDbName.endsWith(".db");
@ -219,7 +220,7 @@ public class DatabaseCommands {
} }
} }
public void onMove(String mainCommand, CMDSender sender, Arguments arguments) { public void onMove(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
DBType fromDB = arguments.get(0).flatMap(DBType::getForName) DBType fromDB = arguments.get(0).flatMap(DBType::getForName)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>")))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>"))));
@ -282,7 +283,7 @@ public class DatabaseCommands {
} }
public void onClear(String mainCommand, CMDSender sender, Arguments arguments) { public void onClear(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
DBType fromDB = arguments.get(0).flatMap(DBType::getForName) DBType fromDB = arguments.get(0).flatMap(DBType::getForName)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>")))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>"))));
@ -335,8 +336,8 @@ public class DatabaseCommands {
} }
} }
public void onFixFabricJoinAddresses(String mainCommand, CMDSender sender, Arguments arguments) { public void onFixFabricJoinAddresses(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
Optional<ServerUUID> serverUUID = identifiers.getServerUUID(identifier); Optional<ServerUUID> serverUUID = identifiers.getServerUUID(identifier);
if (serverUUID.isEmpty()) { if (serverUUID.isEmpty()) {
throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_SERVER_NOT_FOUND, identifier)); throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_SERVER_NOT_FOUND, identifier));
@ -385,8 +386,8 @@ public class DatabaseCommands {
} }
} }
public void onRemove(String mainCommand, CMDSender sender, Arguments arguments) { public void onRemove(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
UUID playerUUID = identifiers.getPlayerUUID(identifier); UUID playerUUID = identifiers.getPlayerUUID(identifier);
if (playerUUID == null) { if (playerUUID == null) {
throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_PLAYER_NOT_FOUND, identifier)); throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_PLAYER_NOT_FOUND, identifier));
@ -444,9 +445,9 @@ public class DatabaseCommands {
} }
} }
public void onUninstalled(CMDSender sender, Arguments arguments) { public void onUninstalled(CMDSender sender, @Untrusted Arguments arguments) {
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
Server server = dbSystem.getDatabase() Server server = dbSystem.getDatabase()
.query(ServerQueries.fetchServerMatchingIdentifier(identifier)) .query(ServerQueries.fetchServerMatchingIdentifier(identifier))
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_SERVER_NOT_FOUND, identifier))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_SERVER_NOT_FOUND, identifier)));
@ -460,7 +461,7 @@ public class DatabaseCommands {
sender.send(locale.getString(CommandLang.DB_UNINSTALLED)); sender.send(locale.getString(CommandLang.DB_UNINSTALLED));
} }
public void onHotswap(CMDSender sender, Arguments arguments) { public void onHotswap(CMDSender sender, @Untrusted Arguments arguments) {
DBType toDB = arguments.get(0).flatMap(DBType::getForName) DBType toDB = arguments.get(0).flatMap(DBType::getForName)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>")))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("<MySQL/SQLite>"))));
@ -482,7 +483,7 @@ public class DatabaseCommands {
statusCommands.onReload(sender); statusCommands.onReload(sender);
} }
public void onOnlineConversion(String mainCommand, CMDSender sender, Arguments arguments) { public void onOnlineConversion(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
boolean removeOfflinePlayers = arguments.get(0) boolean removeOfflinePlayers = arguments.get(0)
.map("--remove_offline"::equals) .map("--remove_offline"::equals)
.orElse(false); .orElse(false);
@ -491,7 +492,7 @@ public class DatabaseCommands {
Map<UUID, BaseUser> baseUsersByUUID = dbSystem.getDatabase().query(BaseUserQueries.fetchAllBaseUsersByUUID()); Map<UUID, BaseUser> baseUsersByUUID = dbSystem.getDatabase().query(BaseUserQueries.fetchAllBaseUsersByUUID());
List<String> playerNames = baseUsersByUUID.values().stream().map(BaseUser::getName).collect(Collectors.toList()); List<String> playerNames = baseUsersByUUID.values().stream().map(BaseUser::getName).collect(Collectors.toList());
sender.send("Performing lookup for " + playerNames.size() + " uuids from Mojang.."); sender.send("Performing lookup for " + playerNames.size() + " uuids from Mojang..");
sender.send("Preparation estimated complete at: " + clock.apply(System.currentTimeMillis() + playerNames.size() * 100) + " (due to request rate limiting)"); sender.send("Preparation estimated complete at: " + clock.apply(System.currentTimeMillis() + playerNames.size() * 100L) + " (due to request rate limiting)");
Map<String, UUID> onlineUUIDsOfPlayers = getUUIDViaUUIDFetcher(playerNames); Map<String, UUID> onlineUUIDsOfPlayers = getUUIDViaUUIDFetcher(playerNames);
if (onlineUUIDsOfPlayers.isEmpty()) { if (onlineUUIDsOfPlayers.isEmpty()) {

View File

@ -33,6 +33,7 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -92,9 +93,9 @@ public class LinkCommands {
* @param sender Sender of command. * @param sender Sender of command.
* @param arguments Given arguments. * @param arguments Given arguments.
*/ */
public void onServerCommand(CMDSender sender, Arguments arguments) { public void onServerCommand(CMDSender sender, @Untrusted Arguments arguments) {
Server server; Server server;
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
server = serverInfo.getServer(); server = serverInfo.getServer();
} else { } else {
@ -117,7 +118,7 @@ public class LinkCommands {
* @param sender Sender of command. * @param sender Sender of command.
* @param arguments Given arguments. * @param arguments Given arguments.
*/ */
public void onServersCommand(CMDSender sender, Arguments arguments) { public void onServersCommand(CMDSender sender, @Untrusted Arguments arguments) {
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
String m = colors.getMainColor(); String m = colors.getMainColor();
String s = colors.getSecondaryColor(); String s = colors.getSecondaryColor();
@ -148,8 +149,8 @@ public class LinkCommands {
* @param sender Sender of command. * @param sender Sender of command.
* @param arguments Given arguments. * @param arguments Given arguments.
*/ */
public void onPlayerCommand(CMDSender sender, Arguments arguments) { public void onPlayerCommand(CMDSender sender, @Untrusted Arguments arguments) {
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
UUID playerUUID = identifiers.getPlayerUUID(identifier); UUID playerUUID = identifiers.getPlayerUUID(identifier);
UUID senderUUID = sender.getUUID().orElse(null); UUID senderUUID = sender.getUUID().orElse(null);
if (playerUUID == null) playerUUID = senderUUID; if (playerUUID == null) playerUUID = senderUUID;
@ -174,7 +175,7 @@ public class LinkCommands {
* @param sender Sender of command * @param sender Sender of command
* @param arguments Only present to fulfill Subcommand#onCommand requirements. * @param arguments Only present to fulfill Subcommand#onCommand requirements.
*/ */
public void onPlayersCommand(CMDSender sender, Arguments arguments) { public void onPlayersCommand(CMDSender sender, @Untrusted Arguments arguments) {
String address = getAddress(sender) + "/players"; String address = getAddress(sender) + "/players";
sender.buildMessage() sender.buildMessage()
.addPart(colors.getMainColor() + locale.getString(CommandLang.LINK_PLAYERS)) .addPart(colors.getMainColor() + locale.getString(CommandLang.LINK_PLAYERS))
@ -188,7 +189,7 @@ public class LinkCommands {
* @param sender Sender of command * @param sender Sender of command
* @param arguments Only present to fulfill Subcommand#onCommand requirements. * @param arguments Only present to fulfill Subcommand#onCommand requirements.
*/ */
public void onNetworkCommand(CMDSender sender, Arguments arguments) { public void onNetworkCommand(CMDSender sender, @Untrusted Arguments arguments) {
String address = getAddress(sender) + "/network"; String address = getAddress(sender) + "/network";
sender.buildMessage() sender.buildMessage()
.addPart(colors.getMainColor() + locale.getString(CommandLang.LINK_NETWORK)) .addPart(colors.getMainColor() + locale.getString(CommandLang.LINK_NETWORK))
@ -205,7 +206,7 @@ public class LinkCommands {
* @param sender Sender of command. * @param sender Sender of command.
* @param arguments Given arguments. * @param arguments Given arguments.
*/ */
public void onWebUsersCommand(CMDSender sender, Arguments arguments) { public void onWebUsersCommand(CMDSender sender, @Untrusted Arguments arguments) {
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
String m = colors.getMainColor(); String m = colors.getMainColor();
String s = colors.getSecondaryColor(); String s = colors.getSecondaryColor();
@ -227,8 +228,8 @@ public class LinkCommands {
} }
} }
public void onJson(CMDSender sender, Arguments arguments) { public void onJson(CMDSender sender, @Untrusted Arguments arguments) {
String identifier = arguments.concatenate(" "); @Untrusted String identifier = arguments.concatenate(" ");
UUID playerUUID = identifiers.getPlayerUUID(identifier); UUID playerUUID = identifiers.getPlayerUUID(identifier);
UUID senderUUID = sender.getUUID().orElse(null); UUID senderUUID = sender.getUUID().orElse(null);
if (playerUUID == null) playerUUID = senderUUID; if (playerUUID == null) playerUUID = senderUUID;

View File

@ -26,6 +26,7 @@ import com.djrapitops.plan.settings.locale.lang.GenericLang;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import com.djrapitops.plan.version.VersionChecker; import com.djrapitops.plan.version.VersionChecker;
@ -33,7 +34,6 @@ import net.playeranalytics.plugin.PluginInformation;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Optional;
@Singleton @Singleton
public class PluginStatusCommands { public class PluginStatusCommands {
@ -80,15 +80,15 @@ public class PluginStatusCommands {
}, "Plan Reload Thread").start(); }, "Plan Reload Thread").start();
} }
public void onDisable(CMDSender sender, Arguments arguments) { public void onDisable(CMDSender sender, @Untrusted Arguments arguments) {
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
plugin.onDisable(); plugin.onDisable();
sender.send(locale.getString(CommandLang.DISABLE_DISABLED)); sender.send(locale.getString(CommandLang.DISABLE_DISABLED));
return; return;
} }
Optional<String> kickCountDisable = arguments.get(0).filter("kickcount"::equalsIgnoreCase); boolean kickCountDisable = arguments.get(0).map("kickcount"::equalsIgnoreCase).orElse(false);
if (kickCountDisable.isPresent()) { if (kickCountDisable) {
status.setCountKicks(false); status.setCountKicks(false);
sender.send(locale.getString(CommandLang.FEATURE_DISABLED, "Kick Counting")); sender.send(locale.getString(CommandLang.FEATURE_DISABLED, "Kick Counting"));
} else { } else {

View File

@ -34,6 +34,7 @@ import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.storage.database.transactions.commands.RemoveWebUserTransaction; import com.djrapitops.plan.storage.database.transactions.commands.RemoveWebUserTransaction;
import com.djrapitops.plan.storage.database.transactions.commands.StoreWebUserTransaction; import com.djrapitops.plan.storage.database.transactions.commands.StoreWebUserTransaction;
import com.djrapitops.plan.utilities.PassEncryptUtil; import com.djrapitops.plan.utilities.PassEncryptUtil;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import net.playeranalytics.plugin.server.PluginLogger; import net.playeranalytics.plugin.server.PluginLogger;
@ -87,7 +88,7 @@ public class RegistrationCommands {
} }
} }
public void onRegister(CMDSender sender, Arguments arguments) { public void onRegister(CMDSender sender, @Untrusted Arguments arguments) {
ensureDatabaseIsOpen(); ensureDatabaseIsOpen();
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
String address = linkCommands.getAddress(sender) + "/register"; String address = linkCommands.getAddress(sender) + "/register";
@ -96,7 +97,7 @@ public class RegistrationCommands {
.apply(builder -> linkCommands.linkTo(builder, sender, address)) .apply(builder -> linkCommands.linkTo(builder, sender, address))
.send(); .send();
} else { } else {
Optional<String> code = arguments.getAfter("--code"); @Untrusted Optional<String> code = arguments.getAfter("--code");
if (code.isPresent()) { if (code.isPresent()) {
registerUsingCode(sender, code.get()); registerUsingCode(sender, code.get());
} else { } else {
@ -105,7 +106,7 @@ public class RegistrationCommands {
} }
} }
public void registerUsingCode(CMDSender sender, String code) { public void registerUsingCode(CMDSender sender, @Untrusted String code) {
UUID linkedToUUID = sender.getUUID().orElse(null); UUID linkedToUUID = sender.getUUID().orElse(null);
Optional<User> user = RegistrationBin.register(code, linkedToUUID); Optional<User> user = RegistrationBin.register(code, linkedToUUID);
if (user.isPresent()) { if (user.isPresent()) {
@ -115,8 +116,8 @@ public class RegistrationCommands {
} }
} }
public void registerUsingLegacy(CMDSender sender, Arguments arguments) { public void registerUsingLegacy(CMDSender sender, @Untrusted Arguments arguments) {
String password = arguments.get(0) @Untrusted String password = arguments.get(0)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, "<password>"))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 1, "<password>")));
String passwordHash = PassEncryptUtil.createHash(password); String passwordHash = PassEncryptUtil.createHash(password);
int permissionLevel = arguments.getInteger(2) int permissionLevel = arguments.getInteger(2)
@ -128,10 +129,10 @@ public class RegistrationCommands {
if (senderUUID.isPresent() && senderName.isPresent()) { if (senderUUID.isPresent() && senderName.isPresent()) {
String playerName = senderName.get(); String playerName = senderName.get();
UUID linkedToUUID = senderUUID.get(); UUID linkedToUUID = senderUUID.get();
String username = arguments.get(1).orElse(playerName); @Untrusted String username = arguments.get(1).orElse(playerName);
registerUser(new User(username, playerName, linkedToUUID, passwordHash, permissionLevel, Collections.emptyList()), sender, permissionLevel); registerUser(new User(username, playerName, linkedToUUID, passwordHash, permissionLevel, Collections.emptyList()), sender, permissionLevel);
} else { } else {
String username = arguments.get(1) @Untrusted String username = arguments.get(1)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 3, "<password> <name> <level>"))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 3, "<password> <name> <level>")));
registerUser(new User(username, "console", null, passwordHash, permissionLevel, Collections.emptyList()), sender, permissionLevel); registerUser(new User(username, "console", null, passwordHash, permissionLevel, Collections.emptyList()), sender, permissionLevel);
} }
@ -170,13 +171,13 @@ public class RegistrationCommands {
} }
} }
public void onUnregister(String mainCommand, CMDSender sender, Arguments arguments) { public void onUnregister(String mainCommand, CMDSender sender, @Untrusted Arguments arguments) {
Optional<String> givenUsername = arguments.get(0).filter(arg -> sender.hasPermission(Permissions.UNREGISTER_OTHER)); @Untrusted Optional<String> givenUsername = arguments.get(0).filter(arg -> sender.hasPermission(Permissions.UNREGISTER_OTHER));
Database database = dbSystem.getDatabase(); Database database = dbSystem.getDatabase();
UUID playerUUID = sender.getUUID().orElse(null); UUID playerUUID = sender.getUUID().orElse(null);
String username; @Untrusted String username;
if (givenUsername.isEmpty() && playerUUID != null) { if (givenUsername.isEmpty() && playerUUID != null) {
username = database.query(WebUserQueries.fetchUser(playerUUID)) username = database.query(WebUserQueries.fetchUser(playerUUID))
.map(User::getUsername) .map(User::getUsername)
@ -231,8 +232,8 @@ public class RegistrationCommands {
} }
public void onLogoutCommand(CMDSender sender, Arguments arguments) { public void onLogoutCommand(CMDSender sender, @Untrusted Arguments arguments) {
String loggingOut = arguments.get(0) @Untrusted String loggingOut = arguments.get(0)
.orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ONE_ARG, locale.getString(HelpLang.ARG_USERNAME) + "/*"))); .orElseThrow(() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ONE_ARG, locale.getString(HelpLang.ARG_USERNAME) + "/*")));
if ("*".equals(loggingOut)) { if ("*".equals(loggingOut)) {

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.commands.use; package com.djrapitops.plan.commands.use;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.TextStringBuilder; import org.apache.commons.text.TextStringBuilder;
@ -29,6 +30,7 @@ import java.util.Optional;
* *
* @author AuroraLS3 * @author AuroraLS3
*/ */
@Untrusted
public class Arguments { public class Arguments {
private final List<String> args; private final List<String> args;

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.commands.use;
import com.djrapitops.plan.settings.locale.Locale; import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.CommandLang; import com.djrapitops.plan.settings.locale.lang.CommandLang;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.TriConsumer; import com.djrapitops.plan.utilities.java.TriConsumer;
import java.util.ArrayList; import java.util.ArrayList;
@ -54,7 +55,7 @@ public class CommandWithSubcommands extends Subcommand {
return subcommands; return subcommands;
} }
public Optional<Subcommand> findSubCommand(Arguments arguments) { public Optional<Subcommand> findSubCommand(@Untrusted Arguments arguments) {
return arguments.get(0).flatMap(alias -> { return arguments.get(0).flatMap(alias -> {
for (Subcommand subcommand : subcommands) { for (Subcommand subcommand : subcommands) {
if (subcommand.getAliases().contains(alias)) { if (subcommand.getAliases().contains(alias)) {
@ -65,7 +66,7 @@ public class CommandWithSubcommands extends Subcommand {
}); });
} }
public void onHelp(CMDSender sender, Arguments arguments) { public void onHelp(CMDSender sender, @Untrusted Arguments arguments) {
List<Subcommand> hasPermissionFor = getPermittedSubcommands(sender); List<Subcommand> hasPermissionFor = getPermittedSubcommands(sender);
sender.buildMessage() sender.buildMessage()
.addPart(locale.getString(CommandLang.HEADER_HELP, getPrimaryAlias())) .addPart(locale.getString(CommandLang.HEADER_HELP, getPrimaryAlias()))
@ -89,7 +90,7 @@ public class CommandWithSubcommands extends Subcommand {
.send(); .send();
} }
public void onCommand(CMDSender sender, Arguments arguments) { public void onCommand(CMDSender sender, @Untrusted Arguments arguments) {
if (sender.isMissingPermissionsFor(this)) { if (sender.isMissingPermissionsFor(this)) {
sender.send(locale.getString(CommandLang.FAIL_NO_PERMISSION) + " " + getRequiredPermissions()); sender.send(locale.getString(CommandLang.FAIL_NO_PERMISSION) + " " + getRequiredPermissions());
return; return;
@ -101,10 +102,10 @@ public class CommandWithSubcommands extends Subcommand {
} }
} }
public void executeCommand(CMDSender sender, Arguments arguments) { public void executeCommand(CMDSender sender, @Untrusted Arguments arguments) {
Optional<String> gotAlias = arguments.get(0); @Untrusted Optional<String> gotAlias = arguments.get(0);
if (gotAlias.isPresent()) { if (gotAlias.isPresent()) {
String alias = gotAlias.get(); @Untrusted String alias = gotAlias.get();
if ("help".equals(alias)) { if ("help".equals(alias)) {
onHelp(sender, arguments); onHelp(sender, arguments);
return; return;
@ -128,8 +129,8 @@ public class CommandWithSubcommands extends Subcommand {
fallback.accept(sender, arguments); fallback.accept(sender, arguments);
} }
public List<String> onTabComplete(CMDSender sender, Arguments arguments) { public List<String> onTabComplete(CMDSender sender, @Untrusted Arguments arguments) {
Optional<String> gotAlias = arguments.get(0); @Untrusted Optional<String> gotAlias = arguments.get(0);
List<String> options = new ArrayList<>(); List<String> options = new ArrayList<>();
if (gotAlias.isPresent()) { if (gotAlias.isPresent()) {
subcommandsLoop: subcommandsLoop:

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.delivery.domain; package com.djrapitops.plan.delivery.domain;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.Objects; import java.util.Objects;
@ -27,6 +28,7 @@ import java.util.Objects;
*/ */
public class Nickname implements DateHolder { public class Nickname implements DateHolder {
@Untrusted
private final String name; private final String name;
private final long date; private final long date;
private final ServerUUID serverUUID; private final ServerUUID serverUUID;
@ -37,6 +39,7 @@ public class Nickname implements DateHolder {
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
} }
@Untrusted
public String getName() { public String getName() {
return name.length() <= 75 ? name : name.substring(0, 74); return name.length() <= 75 ? name : name.substring(0, 74);
} }

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.domain.auth;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser; import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.utilities.PassEncryptUtil; import com.djrapitops.plan.utilities.PassEncryptUtil;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.Collection; import java.util.Collection;
import java.util.Objects; import java.util.Objects;
@ -30,6 +31,7 @@ import java.util.UUID;
*/ */
public class User implements Comparable<User> { public class User implements Comparable<User> {
@Untrusted
private final String username; private final String username;
private final String linkedTo; private final String linkedTo;
private final UUID linkedToUUID; // null for 'console' private final UUID linkedToUUID; // null for 'console'
@ -37,7 +39,7 @@ public class User implements Comparable<User> {
private int permissionLevel; private int permissionLevel;
private final Collection<String> permissions; private final Collection<String> permissions;
public User(String username, String linkedTo, UUID linkedToUUID, String passwordHash, int permissionLevel, Collection<String> permissions) { public User(@Untrusted String username, String linkedTo, UUID linkedToUUID, String passwordHash, int permissionLevel, Collection<String> permissions) {
this.username = username; this.username = username;
this.linkedTo = linkedTo; this.linkedTo = linkedTo;
this.linkedToUUID = linkedToUUID; this.linkedToUUID = linkedToUUID;
@ -46,7 +48,7 @@ public class User implements Comparable<User> {
this.permissions = permissions; this.permissions = permissions;
} }
public boolean doesPasswordMatch(String password) { public boolean doesPasswordMatch(@Untrusted String password) {
return PassEncryptUtil.verifyPassword(password, passwordHash); return PassEncryptUtil.verifyPassword(password, passwordHash);
} }
@ -54,6 +56,7 @@ public class User implements Comparable<User> {
return new WebUser(linkedTo, linkedToUUID, username, permissions); return new WebUser(linkedTo, linkedToUUID, username, permissions);
} }
@Untrusted
public String getUsername() { public String getUsername() {
return username; return username;
} }

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.delivery.domain.datatransfer; package com.djrapitops.plan.delivery.domain.datatransfer;
import com.djrapitops.plan.storage.database.queries.filter.Filter; import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -28,6 +29,7 @@ import java.util.*;
* *
* @author AuroraLS3 * @author AuroraLS3
*/ */
@Untrusted
public class InputFilterDto { public class InputFilterDto {
private final String kind; private final String kind;
@ -38,7 +40,7 @@ public class InputFilterDto {
this.parameters = parameters; this.parameters = parameters;
} }
public static List<InputFilterDto> parse(String json, Gson gson) throws IOException { public static List<InputFilterDto> parse(@Untrusted String json, Gson gson) throws IOException {
return gson.getAdapter(new TypeToken<List<InputFilterDto>>() {}).fromJson(json); return gson.getAdapter(new TypeToken<List<InputFilterDto>>() {}).fromJson(json);
} }

View File

@ -16,11 +16,14 @@
*/ */
package com.djrapitops.plan.delivery.domain.datatransfer; package com.djrapitops.plan.delivery.domain.datatransfer;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class InputQueryDto { public class InputQueryDto {
@Untrusted
public final List<InputFilterDto> filters; public final List<InputFilterDto> filters;
private final ViewDto view; private final ViewDto view;
@ -33,6 +36,7 @@ public class InputQueryDto {
return view; return view;
} }
@Untrusted
public List<InputFilterDto> getFilters() { public List<InputFilterDto> getFilters() {
return filters; return filters;
} }

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.delivery.domain.datatransfer;
import com.djrapitops.plan.delivery.formatting.Formatter; import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters; import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.text.ParseException; import java.text.ParseException;
@ -31,6 +32,7 @@ import java.util.stream.Collectors;
/** /**
* Represents query page view that the user wants to see data for. * Represents query page view that the user wants to see data for.
*/ */
@Untrusted
public class ViewDto { public class ViewDto {
private static final String DATE_PATTERN = "dd/MM/yyyy kk:mm"; private static final String DATE_PATTERN = "dd/MM/yyyy kk:mm";

View File

@ -45,6 +45,7 @@ import com.djrapitops.plan.storage.database.queries.objects.*;
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery; import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery; import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
import com.djrapitops.plan.utilities.comparators.SessionStartComparator; import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import javax.inject.Inject; import javax.inject.Inject;
@ -175,7 +176,7 @@ public class JSONFactory {
return new PlayerKillMutator(kills).toJSONAsMap(formatters); return new PlayerKillMutator(kills).toJSONAsMap(formatters);
} }
public Optional<ServerDto> serverForIdentifier(String identifier) { public Optional<ServerDto> serverForIdentifier(@Untrusted String identifier) {
return dbSystem.getDatabase() return dbSystem.getDatabase()
.query(ServerQueries.fetchServerMatchingIdentifier(identifier)) .query(ServerQueries.fetchServerMatchingIdentifier(identifier))
.map(ServerDto::fromServer); .map(ServerDto::fromServer);

View File

@ -21,7 +21,9 @@ import com.djrapitops.plan.delivery.rendering.html.Contributors;
import com.djrapitops.plan.delivery.rendering.html.Html; import com.djrapitops.plan.delivery.rendering.html.Html;
import com.djrapitops.plan.delivery.rendering.html.icon.Icon; import com.djrapitops.plan.delivery.rendering.html.icon.Icon;
import com.djrapitops.plan.exceptions.ExceptionWithContext; import com.djrapitops.plan.exceptions.ExceptionWithContext;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.version.VersionChecker; import com.djrapitops.plan.version.VersionChecker;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.commons.text.TextStringBuilder; import org.apache.commons.text.TextStringBuilder;
/** /**
@ -32,7 +34,9 @@ import org.apache.commons.text.TextStringBuilder;
public class InternalErrorPage implements Page { public class InternalErrorPage implements Page {
private final String template; private final String template;
@Untrusted
private final String errorMsg; private final String errorMsg;
@Untrusted
private final Throwable error; private final Throwable error;
private final VersionChecker versionChecker; private final VersionChecker versionChecker;
@ -66,13 +70,13 @@ public class InternalErrorPage implements Page {
paragraph.append("Please report this issue here: "); paragraph.append("Please report this issue here: ");
paragraph.append(Html.LINK.create("https://github.com/plan-player-analytics/Plan/issues", "Issues")); paragraph.append(Html.LINK.create("https://github.com/plan-player-analytics/Plan/issues", "Issues"));
paragraph.append("<br><br><pre>"); paragraph.append("<br><br><pre>");
paragraph.append(error).append(" | ").append(errorMsg); paragraph.append(StringEscapeUtils.escapeHtml4(error.toString())).append(" | ").append(StringEscapeUtils.escapeHtml4(errorMsg));
if (error instanceof ExceptionWithContext) { if (error instanceof ExceptionWithContext) {
((ExceptionWithContext) error).getContext() ((ExceptionWithContext) error).getContext()
.ifPresent(context -> paragraph.append(context.getWhatToDo() .ifPresent(context -> paragraph.append(context.getWhatToDo()
.map(whatToDo -> "<br>What to do about it: " + whatToDo) .map(whatToDo -> "<br>What to do about it: " + whatToDo)
.orElse("<br>Error message: " + error.getMessage())) .orElse("<br>Error message: " + StringEscapeUtils.escapeHtml4(error.getMessage())))
.append("<br><br>Related things:<br>") .append("<br><br>Related things:<br>")
.appendWithSeparators(context.toLines(), "<br>") .appendWithSeparators(context.toLines(), "<br>")
.append("<br>")); .append("<br>"));
@ -91,8 +95,8 @@ public class InternalErrorPage implements Page {
return paragraph.toString(); return paragraph.toString();
} }
private void appendCause(Throwable cause, TextStringBuilder paragraph) { private void appendCause(@Untrusted Throwable cause, TextStringBuilder paragraph) {
paragraph.append("<br>Caused by: ").append(cause); paragraph.append("<br>Caused by: ").append(StringEscapeUtils.escapeHtml4(cause.toString()));
for (StackTraceElement element : cause.getStackTrace()) { for (StackTraceElement element : cause.getStackTrace()) {
paragraph.append("<br>"); paragraph.append("<br>");
paragraph.append(" ").append(element); paragraph.append(" ").append(element);

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.delivery.web; package com.djrapitops.plan.delivery.web;
import com.djrapitops.plan.delivery.web.resolver.Resolver; import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -69,7 +70,7 @@ public class ResolverSvc implements ResolverService {
} }
@Override @Override
public List<Resolver> getResolvers(String target) { public List<Resolver> getResolvers(@Untrusted String target) {
List<Resolver> resolvers = new ArrayList<>(); List<Resolver> resolvers = new ArrayList<>();
for (Container container : basicResolvers) { for (Container container : basicResolvers) {
if (container.matcher.test(target)) resolvers.add(container.resolver); if (container.matcher.test(target)) resolvers.add(container.resolver);

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.delivery.webserver; package com.djrapitops.plan.delivery.webserver;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
@ -33,7 +34,7 @@ public class PassBruteForceGuard {
.expireAfterWrite(90, TimeUnit.SECONDS) .expireAfterWrite(90, TimeUnit.SECONDS)
.build(); .build();
public boolean shouldPreventRequest(String accessor) { public boolean shouldPreventRequest(@Untrusted String accessor) {
Integer attempts = failedLoginAttempts.getIfPresent(accessor); Integer attempts = failedLoginAttempts.getIfPresent(accessor);
if (attempts == null) return false; if (attempts == null) return false;
// Too many attempts, forbid further attempts. // Too many attempts, forbid further attempts.
@ -41,7 +42,7 @@ public class PassBruteForceGuard {
} }
// Don't call on first connection. // Don't call on first connection.
public void increaseAttemptCountOnFailedLogin(String accessor) { public void increaseAttemptCountOnFailedLogin(@Untrusted String accessor) {
// Authentication was attempted, but failed so new attempt is going to be given if not forbidden // Authentication was attempted, but failed so new attempt is going to be given if not forbidden
failedLoginAttempts.cleanUp(); failedLoginAttempts.cleanUp();
@ -59,7 +60,7 @@ public class PassBruteForceGuard {
failedLoginAttempts.put(accessor, attempts + 1); failedLoginAttempts.put(accessor, attempts + 1);
} }
public void resetAttemptCount(String accessor) { public void resetAttemptCount(@Untrusted String accessor) {
// Successful login // Successful login
failedLoginAttempts.cleanUp(); failedLoginAttempts.cleanUp();
failedLoginAttempts.invalidate(accessor); failedLoginAttempts.invalidate(accessor);

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.webserver;
import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.URIQuery; import com.djrapitops.plan.delivery.web.resolver.request.URIQuery;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -38,7 +39,7 @@ public class RequestBodyConverter {
return new URIQuery(new String(request.getRequestBody(), StandardCharsets.UTF_8)); return new URIQuery(new String(request.getRequestBody(), StandardCharsets.UTF_8));
} }
public static <T> T bodyJson(Request request, Gson gson, Class<T> ofType) { public static <T> T bodyJson(@Untrusted Request request, Gson gson, Class<T> ofType) {
return gson.fromJson(new String(request.getRequestBody(), StandardCharsets.UTF_8), ofType); return gson.fromJson(new String(request.getRequestBody(), StandardCharsets.UTF_8), ofType);
} }

View File

@ -36,10 +36,12 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries; import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import com.djrapitops.plan.utilities.java.UnaryChain; import com.djrapitops.plan.utilities.java.UnaryChain;
import dagger.Lazy; import dagger.Lazy;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -375,11 +377,11 @@ public class ResponseFactory {
.build(); .build();
} }
public Response ipWhitelist403(String accessor) { public Response ipWhitelist403(@Untrusted String accessor) {
return Response.builder() return Response.builder()
.setMimeType(MimeType.HTML) .setMimeType(MimeType.HTML)
.setContent("<h1>403 Forbidden</h1>" + .setContent("<h1>403 Forbidden</h1>" +
"<p>IP-whitelist enabled, \"" + accessor + "\" is not on the list!</p>") "<p>IP-whitelist enabled, \"" + StringEscapeUtils.escapeHtml4(accessor) + "\" is not on the list!</p>")
.setStatus(403) .setStatus(403)
.build(); .build();
} }

View File

@ -34,6 +34,7 @@ import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerJsonResolv
import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerPageResolver; import com.djrapitops.plan.delivery.webserver.resolver.swagger.SwaggerPageResolver;
import com.djrapitops.plan.exceptions.WebUserAuthException; import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.connection.ForbiddenException; import com.djrapitops.plan.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import dagger.Lazy; import dagger.Lazy;
@ -167,7 +168,7 @@ public class ResponseResolver {
return request -> Optional.of(response.get()); return request -> Optional.of(response.get());
} }
public Response getResponse(Request request) { public Response getResponse(@Untrusted Request request) {
try { try {
return tryToGetResponse(request); return tryToGetResponse(request);
} catch (NotFoundException e) { } catch (NotFoundException e) {
@ -189,7 +190,7 @@ public class ResponseResolver {
* @throws ForbiddenException If the user is not allowed to see the page * @throws ForbiddenException If the user is not allowed to see the page
* @throws BadRequestException If the request did not have required things. * @throws BadRequestException If the request did not have required things.
*/ */
private Response tryToGetResponse(Request request) { private Response tryToGetResponse(@Untrusted Request request) {
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
return Response.builder().setStatus(204).build(); return Response.builder().setStatus(204).build();

View File

@ -25,6 +25,7 @@ import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.storage.database.transactions.events.CookieChangeTransaction; import com.djrapitops.plan.storage.database.transactions.events.CookieChangeTransaction;
import com.djrapitops.plan.utilities.dev.Untrusted;
import net.playeranalytics.plugin.server.PluginLogger; import net.playeranalytics.plugin.server.PluginLogger;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@ -70,7 +71,7 @@ public class ActiveCookieStore implements SubSystem {
Holder.getActiveCookieStore().removeCookie(cookie); Holder.getActiveCookieStore().removeCookie(cookie);
} }
public static void removeUserCookie(String username) { public static void removeUserCookie(@Untrusted String username) {
USERS_BY_COOKIE.entrySet().stream().filter(entry -> entry.getValue().getUsername().equals(username)) USERS_BY_COOKIE.entrySet().stream().filter(entry -> entry.getValue().getUsername().equals(username))
.findAny() .findAny()
.map(Map.Entry::getKey) .map(Map.Entry::getKey)
@ -106,7 +107,7 @@ public class ActiveCookieStore implements SubSystem {
USERS_BY_COOKIE.clear(); USERS_BY_COOKIE.clear();
} }
public Optional<User> checkCookie(String cookie) { public Optional<User> checkCookie(@Untrusted String cookie) {
return Optional.ofNullable(USERS_BY_COOKIE.get(cookie)); return Optional.ofNullable(USERS_BY_COOKIE.get(cookie));
} }
@ -124,14 +125,14 @@ public class ActiveCookieStore implements SubSystem {
)); ));
} }
public void removeCookie(String cookie) { public void removeCookie(@Untrusted String cookie) {
checkCookie(cookie).map(User::getUsername) checkCookie(cookie).map(User::getUsername)
.ifPresent(this::deleteCookieByUser); .ifPresent(this::deleteCookieByUser);
USERS_BY_COOKIE.remove(cookie); USERS_BY_COOKIE.remove(cookie);
deleteCookie(cookie); deleteCookie(cookie);
} }
private void deleteCookie(String cookie) { private void deleteCookie(@Untrusted String cookie) {
dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.removeCookie(cookie)); dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.removeCookie(cookie));
} }

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.WebserverSettings; import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -44,7 +45,7 @@ public class AllowedIpList {
} }
} }
public boolean isAllowed(String accessAddress) { public boolean isAllowed(@Untrusted String accessAddress) {
prepare(); prepare();
List<String> ips = allowList.get(); List<String> ips = allowList.get();

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.delivery.webserver.auth; package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.delivery.webserver.http.InternalRequest; import com.djrapitops.plan.delivery.webserver.http.InternalRequest;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -37,8 +38,8 @@ public class AuthenticationExtractor {
return getCookieAuthentication(internalRequest.getCookies()); return getCookieAuthentication(internalRequest.getCookies());
} }
private Optional<Authentication> getCookieAuthentication(List<Cookie> cookies) { private Optional<Authentication> getCookieAuthentication(@Untrusted List<Cookie> cookies) {
for (Cookie cookie : cookies) { for (@Untrusted Cookie cookie : cookies) {
if ("auth".equals(cookie.getName())) { if ("auth".equals(cookie.getName())) {
return Optional.of(new CookieAuthentication(activeCookieStore, cookie.getValue())); return Optional.of(new CookieAuthentication(activeCookieStore, cookie.getValue()));
} }

View File

@ -16,8 +16,10 @@
*/ */
package com.djrapitops.plan.delivery.webserver.auth; package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@Untrusted
public class Cookie { public class Cookie {
private final String name; private final String name;

View File

@ -17,13 +17,15 @@
package com.djrapitops.plan.delivery.webserver.auth; package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.delivery.domain.auth.User;
import com.djrapitops.plan.utilities.dev.Untrusted;
public class CookieAuthentication implements Authentication { public class CookieAuthentication implements Authentication {
private final ActiveCookieStore activeCookieStore; private final ActiveCookieStore activeCookieStore;
@Untrusted
private final String cookie; private final String cookie;
public CookieAuthentication(ActiveCookieStore activeCookieStore, String cookie) { public CookieAuthentication(ActiveCookieStore activeCookieStore, @Untrusted String cookie) {
this.activeCookieStore = activeCookieStore; this.activeCookieStore = activeCookieStore;
this.cookie = cookie; this.cookie = cookie;
} }

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.delivery.domain.auth.User; import com.djrapitops.plan.delivery.domain.auth.User;
import com.djrapitops.plan.utilities.PassEncryptUtil; import com.djrapitops.plan.utilities.PassEncryptUtil;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@ -42,29 +43,30 @@ public class RegistrationBin {
// Hide static cache constructor // Hide static cache constructor
} }
public static String addInfoForRegistration(String username, String password) { public static String addInfoForRegistration(@Untrusted String username, @Untrusted String password) {
String hash = PassEncryptUtil.createHash(password); String hash = PassEncryptUtil.createHash(password);
String code = DigestUtils.sha256Hex(username + password + System.currentTimeMillis()).substring(0, 12); String code = DigestUtils.sha256Hex(username + password + System.currentTimeMillis()).substring(0, 12);
REGISTRATION_BIN.put(code, new AwaitingForRegistration(username, hash)); REGISTRATION_BIN.put(code, new AwaitingForRegistration(username, hash));
return code; return code;
} }
public static Optional<User> register(String code, UUID linkedToUUID) { public static Optional<User> register(@Untrusted String code, UUID linkedToUUID) {
AwaitingForRegistration found = REGISTRATION_BIN.getIfPresent(code); AwaitingForRegistration found = REGISTRATION_BIN.getIfPresent(code);
if (found == null) return Optional.empty(); if (found == null) return Optional.empty();
REGISTRATION_BIN.invalidate(code); REGISTRATION_BIN.invalidate(code);
return Optional.of(found.toUser(linkedToUUID)); return Optional.of(found.toUser(linkedToUUID));
} }
public static boolean contains(String code) { public static boolean contains(@Untrusted String code) {
return REGISTRATION_BIN.getIfPresent(code) != null; return REGISTRATION_BIN.getIfPresent(code) != null;
} }
private static class AwaitingForRegistration { private static class AwaitingForRegistration {
@Untrusted
private final String username; private final String username;
private final String passwordHash; private final String passwordHash;
public AwaitingForRegistration(String username, String passwordHash) { public AwaitingForRegistration(@Untrusted String username, String passwordHash) {
this.username = username; this.username = username;
this.passwordHash = passwordHash; this.passwordHash = passwordHash;
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.webserver.Addresses;
import com.djrapitops.plan.settings.config.paths.WebserverSettings; import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.settings.locale.Locale; import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.PluginLang; import com.djrapitops.plan.settings.locale.lang.PluginLang;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import net.playeranalytics.plugin.server.PluginLogger; import net.playeranalytics.plugin.server.PluginLogger;
@ -61,7 +62,7 @@ public class WebserverLogMessages {
} }
} }
public void warnAboutWhitelistBlock(String accessAddress, String requestedURIString) { public void warnAboutWhitelistBlock(@Untrusted String accessAddress, @Untrusted String requestedURIString) {
logger.info(locale.getString(PluginLang.WEB_SERVER_NOTIFY_IP_WHITELIST_BLOCK, accessAddress, requestedURIString)); logger.info(locale.getString(PluginLang.WEB_SERVER_NOTIFY_IP_WHITELIST_BLOCK, accessAddress, requestedURIString));
} }

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfigurati
import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.exceptions.database.DBOpException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.transactions.events.StoreRequestTransaction; import com.djrapitops.plan.storage.database.transactions.events.StoreRequestTransaction;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import net.playeranalytics.plugin.server.PluginLogger; import net.playeranalytics.plugin.server.PluginLogger;
@ -46,10 +47,10 @@ public class AccessLogger {
this.errorLogger = errorLogger; this.errorLogger = errorLogger;
} }
public void log(InternalRequest internalRequest, Request request, Response response) { public void log(@Untrusted InternalRequest internalRequest, @Untrusted Request request, Response response) {
if (webserverConfiguration.logAccessToConsole()) { if (webserverConfiguration.logAccessToConsole()) {
int code = response.getCode(); int code = response.getCode();
String message = "Access Log: " + internalRequest.getMethod() + " " + @Untrusted String message = "Access Log: " + internalRequest.getMethod() + " " +
getRequestURI(internalRequest, request) + getRequestURI(internalRequest, request) +
" (from " + internalRequest.getAccessAddress(webserverConfiguration) + ") - " + " (from " + internalRequest.getAccessAddress(webserverConfiguration) + ") - " +
code; code;
@ -82,6 +83,7 @@ public class AccessLogger {
} }
} }
@Untrusted
private String getRequestURI(InternalRequest internalRequest, Request request) { private String getRequestURI(InternalRequest internalRequest, Request request) {
return request != null ? request.getPath().asString() + request.getQuery().asString() return request != null ? request.getPath().asString() + request.getQuery().asString()
: internalRequest.getRequestedURIString(); : internalRequest.getRequestedURIString();

View File

@ -23,6 +23,7 @@ import com.djrapitops.plan.delivery.webserver.auth.Authentication;
import com.djrapitops.plan.delivery.webserver.auth.AuthenticationExtractor; import com.djrapitops.plan.delivery.webserver.auth.AuthenticationExtractor;
import com.djrapitops.plan.delivery.webserver.auth.Cookie; import com.djrapitops.plan.delivery.webserver.auth.Cookie;
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration; import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -36,10 +37,11 @@ public interface InternalRequest {
long getTimestamp(); long getTimestamp();
@Untrusted
default String getAccessAddress(WebserverConfiguration webserverConfiguration) { default String getAccessAddress(WebserverConfiguration webserverConfiguration) {
AccessAddressPolicy accessAddressPolicy = webserverConfiguration.getAccessAddressPolicy(); AccessAddressPolicy accessAddressPolicy = webserverConfiguration.getAccessAddressPolicy();
if (accessAddressPolicy == AccessAddressPolicy.X_FORWARDED_FOR_HEADER) { if (accessAddressPolicy == AccessAddressPolicy.X_FORWARDED_FOR_HEADER) {
String fromHeader = getAccessAddressFromHeader(); @Untrusted String fromHeader = getAccessAddressFromHeader();
if (fromHeader == null) { if (fromHeader == null) {
webserverConfiguration.getWebserverLogMessages().warnAboutXForwardedForSecurityIssue(); webserverConfiguration.getWebserverLogMessages().warnAboutXForwardedForSecurityIssue();
return getAccessAddressFromSocketIp(); return getAccessAddressFromSocketIp();

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.auth.AuthenticationExtractor; import com.djrapitops.plan.delivery.webserver.auth.AuthenticationExtractor;
import com.djrapitops.plan.delivery.webserver.auth.Cookie; import com.djrapitops.plan.delivery.webserver.auth.Cookie;
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration; import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
import com.djrapitops.plan.utilities.dev.Untrusted;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.text.TextStringBuilder; import org.apache.commons.text.TextStringBuilder;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
@ -72,11 +73,11 @@ public class JettyInternalRequest implements InternalRequest {
@Override @Override
public com.djrapitops.plan.delivery.web.resolver.request.Request toRequest() { public com.djrapitops.plan.delivery.web.resolver.request.Request toRequest() {
String requestMethod = baseRequest.getMethod(); String requestMethod = baseRequest.getMethod();
URIPath path = new URIPath(baseRequest.getHttpURI().getDecodedPath()); @Untrusted URIPath path = new URIPath(baseRequest.getHttpURI().getDecodedPath());
URIQuery query = new URIQuery(baseRequest.getHttpURI().getQuery()); @Untrusted URIQuery query = new URIQuery(baseRequest.getHttpURI().getQuery());
byte[] requestBody = readRequestBody(); @Untrusted byte[] requestBody = readRequestBody();
WebUser user = getWebUser(webserverConfiguration, authenticationExtractor); WebUser user = getWebUser(webserverConfiguration, authenticationExtractor);
Map<String, String> headers = getRequestHeaders(); @Untrusted Map<String, String> headers = getRequestHeaders();
return new com.djrapitops.plan.delivery.web.resolver.request.Request(requestMethod, path, query, user, headers, requestBody); return new com.djrapitops.plan.delivery.web.resolver.request.Request(requestMethod, path, query, user, headers, requestBody);
} }
@ -106,7 +107,7 @@ public class JettyInternalRequest implements InternalRequest {
@Override @Override
public List<Cookie> getCookies() { public List<Cookie> getCookies() {
List<String> textCookies = getCookieHeaders(); @Untrusted List<String> textCookies = getCookieHeaders();
List<Cookie> cookies = new ArrayList<>(); List<Cookie> cookies = new ArrayList<>();
if (!textCookies.isEmpty()) { if (!textCookies.isEmpty()) {
String[] separated = new TextStringBuilder().appendWithSeparators(textCookies, ";").build().split(";"); String[] separated = new TextStringBuilder().appendWithSeparators(textCookies, ";").build().split(";");

View File

@ -24,6 +24,7 @@ import com.djrapitops.plan.delivery.webserver.ResponseResolver;
import com.djrapitops.plan.delivery.webserver.auth.FailReason; import com.djrapitops.plan.delivery.webserver.auth.FailReason;
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration; import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
import com.djrapitops.plan.exceptions.WebUserAuthException; import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
@ -52,10 +53,10 @@ public class RequestHandler {
} }
public Response getResponse(InternalRequest internalRequest) { public Response getResponse(InternalRequest internalRequest) {
String accessAddress = internalRequest.getAccessAddress(webserverConfiguration); @Untrusted String accessAddress = internalRequest.getAccessAddress(webserverConfiguration);
Response response; Response response;
Request request = null; @Untrusted Request request = null;
if (bruteForceGuard.shouldPreventRequest(accessAddress)) { if (bruteForceGuard.shouldPreventRequest(accessAddress)) {
response = responseFactory.failedLoginAttempts403(); response = responseFactory.failedLoginAttempts403();
} else if (!webserverConfiguration.getAllowedIpList().isAllowed(accessAddress)) { } else if (!webserverConfiguration.getAllowedIpList().isAllowed(accessAddress)) {
@ -81,17 +82,17 @@ public class RequestHandler {
return response; return response;
} }
private Response attemptToResolve(Request request, String accessAddress) { private Response attemptToResolve(@Untrusted Request request, @Untrusted String accessAddress) {
Response response = protocolUpgradeResponse(request) Response response = protocolUpgradeResponse(request)
.orElseGet(() -> responseResolver.getResponse(request)); .orElseGet(() -> responseResolver.getResponse(request));
request.getUser().ifPresent(user -> processSuccessfulLogin(response.getCode(), accessAddress)); request.getUser().ifPresent(user -> processSuccessfulLogin(response.getCode(), accessAddress));
return response; return response;
} }
private Optional<Response> protocolUpgradeResponse(Request request) { private Optional<Response> protocolUpgradeResponse(@Untrusted Request request) {
Optional<String> upgrade = request.getHeader(HttpHeader.UPGRADE.asString()); @Untrusted Optional<String> upgrade = request.getHeader(HttpHeader.UPGRADE.asString());
if (upgrade.isPresent()) { if (upgrade.isPresent()) {
String value = upgrade.get(); @Untrusted String value = upgrade.get();
if ("h2c".equals(value) || "h2".equals(value)) { if ("h2c".equals(value) || "h2".equals(value)) {
return Optional.of(Response.builder() return Optional.of(Response.builder()
.setStatus(101) .setStatus(101)
@ -103,12 +104,12 @@ public class RequestHandler {
return Optional.empty(); return Optional.empty();
} }
private Response processFailedAuthentication(InternalRequest internalRequest, String accessAddress, WebUserAuthException thrownByAuthentication) { private Response processFailedAuthentication(InternalRequest internalRequest, @Untrusted String accessAddress, WebUserAuthException thrownByAuthentication) {
FailReason failReason = thrownByAuthentication.getFailReason(); FailReason failReason = thrownByAuthentication.getFailReason();
if (failReason == FailReason.USER_PASS_MISMATCH) { if (failReason == FailReason.USER_PASS_MISMATCH) {
return processWrongPassword(accessAddress, failReason); return processWrongPassword(accessAddress, failReason);
} else { } else {
String from = internalRequest.getRequestedURIString(); @Untrusted String from = internalRequest.getRequestedURIString();
String directTo = StringUtils.startsWithAny(from, "/auth/", "/login") ? "/login" : "/login?from=." + from; String directTo = StringUtils.startsWithAny(from, "/auth/", "/login") ? "/login" : "/login?from=." + from;
return Response.builder() return Response.builder()
.redirectTo(directTo) .redirectTo(directTo)
@ -117,7 +118,7 @@ public class RequestHandler {
} }
} }
private Response processWrongPassword(String accessAddress, FailReason failReason) { private Response processWrongPassword(@Untrusted String accessAddress, FailReason failReason) {
bruteForceGuard.increaseAttemptCountOnFailedLogin(accessAddress); bruteForceGuard.increaseAttemptCountOnFailedLogin(accessAddress);
if (bruteForceGuard.shouldPreventRequest(accessAddress)) { if (bruteForceGuard.shouldPreventRequest(accessAddress)) {
return responseFactory.failedLoginAttempts403(); return responseFactory.failedLoginAttempts403();
@ -126,7 +127,7 @@ public class RequestHandler {
} }
} }
private void processSuccessfulLogin(int responseCode, String accessAddress) { private void processSuccessfulLogin(int responseCode, @Untrusted String accessAddress) {
boolean successfulLogin = responseCode != 401; boolean successfulLogin = responseCode != 401;
boolean notForbidden = responseCode != 403; boolean notForbidden = responseCode != 403;
if (successfulLogin && notForbidden) { if (successfulLogin && notForbidden) {

View File

@ -26,7 +26,9 @@ import com.djrapitops.plan.delivery.webserver.ResponseFactory;
import com.djrapitops.plan.identification.UUIDUtility; import com.djrapitops.plan.identification.UUIDUtility;
import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.PluginSettings; import com.djrapitops.plan.settings.config.paths.PluginSettings;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -60,17 +62,22 @@ public class PlayerPageResolver implements Resolver {
public boolean canAccess(Request request) { public boolean canAccess(Request request) {
URIPath path = request.getPath(); URIPath path = request.getPath();
WebUser user = request.getUser().orElse(new WebUser("")); WebUser user = request.getUser().orElse(new WebUser(""));
boolean isOwnPage = path.getPart(1).map(nameOrUUID -> { boolean isOwnPage = isOwnPage(path, user);
return user.hasPermission("page.player.other") || user.hasPermission("page.player.self") && isOwnPage;
}
@NotNull
private Boolean isOwnPage(@Untrusted URIPath path, WebUser user) {
return path.getPart(1).map(nameOrUUID -> {
if (user.getName().equalsIgnoreCase(nameOrUUID)) return true; // name matches user if (user.getName().equalsIgnoreCase(nameOrUUID)) return true; // name matches user
return uuidUtility.getNameOf(nameOrUUID).map(user.getName()::equalsIgnoreCase) // uuid matches user return uuidUtility.getNameOf(nameOrUUID).map(user.getName()::equalsIgnoreCase) // uuid matches user
.orElse(false); // uuid or name don't match .orElse(false); // uuid or name don't match
}).orElse(true); // No name or UUID given }).orElse(true); // No name or UUID given
return user.hasPermission("page.player.other") || user.hasPermission("page.player.self") && isOwnPage;
} }
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(Request request) {
URIPath path = request.getPath(); @Untrusted URIPath path = request.getPath();
if (StringUtils.containsAny(path.asString(), "/vendor/", "/js/", "/css/", "/img/", "/static/")) { if (StringUtils.containsAny(path.asString(), "/vendor/", "/js/", "/css/", "/img/", "/static/")) {
return Optional.empty(); return Optional.empty();
} }
@ -78,7 +85,7 @@ public class PlayerPageResolver implements Resolver {
.map(playerName -> getResponse(request.getPath(), playerName)); .map(playerName -> getResponse(request.getPath(), playerName));
} }
private Response getResponse(URIPath path, String playerName) { private Response getResponse(@Untrusted URIPath path, @Untrusted String playerName) {
UUID playerUUID = uuidUtility.getUUIDOf(playerName); UUID playerUUID = uuidUtility.getUUIDOf(playerName);
if (playerUUID == null) return responseFactory.uuidNotFound404(); if (playerUUID == null) return responseFactory.uuidNotFound404();

View File

@ -32,6 +32,7 @@ import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
/** /**
* Resolves '/' URL (Address Root). * Resolves '/' URL (Address Root).
@ -72,7 +73,7 @@ public class RootPageResolver implements NoAuthResolver {
} else if (user.hasPermission("page.players")) { } else if (user.hasPermission("page.players")) {
return responseFactory.redirectResponse("players"); return responseFactory.redirectResponse("players");
} else if (user.hasPermission("page.player.self")) { } else if (user.hasPermission("page.player.self")) {
return responseFactory.redirectResponse("player/" + Html.encodeToURL(user.getName())); return responseFactory.redirectResponse("player/" + user.getUUID().map(UUID::toString).orElseGet(user::getName));
} else { } else {
return responseFactory.forbidden403(user.getName() + " has insufficient permissions to be redirected to any page. Needs one of: 'page.server', 'page.players' or 'page.player.self'"); return responseFactory.forbidden403(user.getName() + " has insufficient permissions to be redirected to any page. Needs one of: 'page.server', 'page.players' or 'page.player.self'");
} }

View File

@ -28,6 +28,7 @@ import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -58,7 +59,7 @@ public class ServerPageResolver implements Resolver {
@Override @Override
public boolean canAccess(Request request) { public boolean canAccess(Request request) {
String firstPart = request.getPath().getPart(0).orElse(""); @Untrusted String firstPart = request.getPath().getPart(0).orElse("");
WebUser permissions = request.getUser().orElse(new WebUser("")); WebUser permissions = request.getUser().orElse(new WebUser(""));
boolean forServerPage = "server".equalsIgnoreCase(firstPart) && permissions.hasPermission("page.server"); boolean forServerPage = "server".equalsIgnoreCase(firstPart) && permissions.hasPermission("page.server");
boolean forNetworkPage = "network".equalsIgnoreCase(firstPart) && permissions.hasPermission("page.network"); boolean forNetworkPage = "network".equalsIgnoreCase(firstPart) && permissions.hasPermission("page.network");
@ -92,7 +93,7 @@ public class ServerPageResolver implements Resolver {
return Optional.of(responseFactory.serverPageResponse(serverUUID)); return Optional.of(responseFactory.serverPageResponse(serverUUID));
} }
private Optional<ServerUUID> getServerUUID(URIPath path) { private Optional<ServerUUID> getServerUUID(@Untrusted URIPath path) {
if (serverInfo.getServer().isProxy() if (serverInfo.getServer().isProxy()
&& path.getPart(0).map("network"::equals).orElse(false) && path.getPart(0).map("network"::equals).orElse(false)
) { ) {

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.URIPath; import com.djrapitops.plan.delivery.web.resolver.request.URIPath;
import com.djrapitops.plan.delivery.webserver.ResponseFactory; import com.djrapitops.plan.delivery.webserver.ResponseFactory;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject; import javax.inject.Inject;
@ -51,7 +52,7 @@ public class StaticResourceResolver implements NoAuthResolver {
} }
private Response getResponse(Request request) { private Response getResponse(Request request) {
String resource = getPath(request).asString().substring(1); @Untrusted String resource = getPath(request).asString().substring(1);
if (resource.endsWith(".css")) { if (resource.endsWith(".css")) {
return responseFactory.cssResponse(resource); return responseFactory.cssResponse(resource);
} }
@ -68,7 +69,7 @@ public class StaticResourceResolver implements NoAuthResolver {
} }
private URIPath getPath(Request request) { private URIPath getPath(Request request) {
URIPath path = request.getPath(); @Untrusted URIPath path = request.getPath();
// Remove everything before /vendor /css /js or /img // Remove everything before /vendor /css /js or /img
while (!path.getPart(0).map(part -> part.matches(PART_REGEX)).orElse(true)) { while (!path.getPart(0).map(part -> part.matches(PART_REGEX)).orElse(true)) {
path = path.omitFirst(); path = path.omitFirst();

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser; import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.ResponseFactory; import com.djrapitops.plan.delivery.webserver.ResponseFactory;
import com.djrapitops.plan.delivery.webserver.http.WebServer; import com.djrapitops.plan.delivery.webserver.http.WebServer;
import com.djrapitops.plan.utilities.dev.Untrusted;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
@ -44,10 +45,10 @@ public class LoginPageResolver implements NoAuthResolver {
} }
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(@Untrusted Request request) {
Optional<WebUser> user = request.getUser(); Optional<WebUser> user = request.getUser();
if (user.isPresent() || !webServer.get().isAuthRequired()) { if (user.isPresent() || !webServer.get().isAuthRequired()) {
Optional<String> from = request.getQuery().get("from") @Untrusted Optional<String> from = request.getQuery().get("from")
.filter(redirectBackTo -> !redirectBackTo.startsWith("http")); .filter(redirectBackTo -> !redirectBackTo.startsWith("http"));
return Optional.of(responseFactory.redirectResponse(from.orElse("/"))); return Optional.of(responseFactory.redirectResponse(from.orElse("/")));
} }

View File

@ -30,6 +30,7 @@ import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.exceptions.database.DBOpException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.ExampleObject;
@ -92,11 +93,11 @@ public class LoginResolver implements NoAuthResolver {
.build(); .build();
} }
public User getUser(Request request) { public User getUser(@Untrusted Request request) {
URIQuery form = RequestBodyConverter.formBody(request); @Untrusted URIQuery form = RequestBodyConverter.formBody(request);
URIQuery query = request.getQuery(); @Untrusted URIQuery query = request.getQuery();
String username = getUser(form, query); @Untrusted String username = getUser(form, query);
String password = getPassword(form, query); @Untrusted String password = getPassword(form, query);
User user = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username)) User user = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username))
.orElseThrow(() -> new WebUserAuthException(FailReason.USER_PASS_MISMATCH)); .orElseThrow(() -> new WebUserAuthException(FailReason.USER_PASS_MISMATCH));
@ -107,13 +108,13 @@ public class LoginResolver implements NoAuthResolver {
return user; return user;
} }
private String getPassword(URIQuery form, URIQuery query) { private String getPassword(@Untrusted URIQuery form, @Untrusted URIQuery query) {
return form.get("password") return form.get("password")
.orElseGet(() -> query.get("password") .orElseGet(() -> query.get("password")
.orElseThrow(() -> new BadRequestException("'password' parameter not defined"))); .orElseThrow(() -> new BadRequestException("'password' parameter not defined")));
} }
private String getUser(URIQuery form, URIQuery query) { private String getUser(@Untrusted URIQuery form, @Untrusted URIQuery query) {
return form.get("user") return form.get("user")
.orElseGet(() -> query.get("user") .orElseGet(() -> query.get("user")
.orElseThrow(() -> new BadRequestException("'user' parameter not defined"))); .orElseThrow(() -> new BadRequestException("'user' parameter not defined")));

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieStore; import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieStore;
import com.djrapitops.plan.delivery.webserver.auth.FailReason; import com.djrapitops.plan.delivery.webserver.auth.FailReason;
import com.djrapitops.plan.exceptions.WebUserAuthException; import com.djrapitops.plan.exceptions.WebUserAuthException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.ExampleObject;
@ -57,13 +58,13 @@ public class LogoutResolver implements NoAuthResolver {
requestBody = @RequestBody(content = @Content(examples = @ExampleObject())) requestBody = @RequestBody(content = @Content(examples = @ExampleObject()))
) )
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(@Untrusted Request request) {
String cookies = request.getHeader("Cookie").orElse(""); @Untrusted String cookies = request.getHeader("Cookie").orElse("");
String foundCookie = null; @Untrusted String foundCookie = null;
for (String cookie : cookies.split(";")) { for (@Untrusted String cookie : cookies.split(";")) {
if (cookie.isEmpty()) continue; if (cookie.isEmpty()) continue;
String[] split = cookie.split("="); @Untrusted String[] split = cookie.split("=");
String name = split[0]; @Untrusted String name = split[0];
if ("auth".equals(name) && split.length > 1) { if ("auth".equals(name) && split.length > 1) {
foundCookie = split[1]; foundCookie = split[1];
activeCookieStore.removeCookie(foundCookie); activeCookieStore.removeCookie(foundCookie);

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser; import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.delivery.webserver.ResponseFactory; import com.djrapitops.plan.delivery.webserver.ResponseFactory;
import com.djrapitops.plan.delivery.webserver.http.WebServer; import com.djrapitops.plan.delivery.webserver.http.WebServer;
import com.djrapitops.plan.utilities.dev.Untrusted;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
@ -44,7 +45,7 @@ public class RegisterPageResolver implements NoAuthResolver {
} }
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(@Untrusted Request request) {
Optional<WebUser> user = request.getUser(); Optional<WebUser> user = request.getUser();
if (user.isPresent() || !webServer.get().isAuthRequired()) { if (user.isPresent() || !webServer.get().isAuthRequired()) {
return Optional.of(responseFactory.redirectResponse("/")); return Optional.of(responseFactory.redirectResponse("/"));

View File

@ -27,6 +27,7 @@ import com.djrapitops.plan.delivery.webserver.auth.RegistrationBin;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.utilities.PassEncryptUtil; import com.djrapitops.plan.utilities.PassEncryptUtil;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -79,8 +80,8 @@ public class RegisterResolver implements NoAuthResolver {
} }
public Response getResponse(Request request) { public Response getResponse(Request request) {
URIQuery query = request.getQuery(); @Untrusted URIQuery query = request.getQuery();
Optional<String> checkCode = query.get("code"); @Untrusted Optional<String> checkCode = query.get("code");
if (checkCode.isPresent()) { if (checkCode.isPresent()) {
return Response.builder() return Response.builder()
.setStatus(200) .setStatus(200)
@ -88,13 +89,13 @@ public class RegisterResolver implements NoAuthResolver {
.build(); .build();
} }
URIQuery form = RequestBodyConverter.formBody(request); @Untrusted URIQuery form = RequestBodyConverter.formBody(request);
String username = getUser(form, query); @Untrusted String username = getUser(form, query);
boolean alreadyExists = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username)).isPresent(); boolean alreadyExists = dbSystem.getDatabase().query(WebUserQueries.fetchUser(username)).isPresent();
if (alreadyExists) throw new BadRequestException("User already exists!"); if (alreadyExists) throw new BadRequestException("User already exists!");
String password = getPassword(form, query); @Untrusted String password = getPassword(form, query);
try { try {
String code = RegistrationBin.addInfoForRegistration(username, password); String code = RegistrationBin.addInfoForRegistration(username, password);
return Response.builder() return Response.builder()
@ -109,13 +110,13 @@ public class RegisterResolver implements NoAuthResolver {
} }
} }
private String getPassword(URIQuery form, URIQuery query) { private String getPassword(@Untrusted URIQuery form, @Untrusted URIQuery query) {
return form.get("password") return form.get("password")
.orElseGet(() -> query.get("password") .orElseGet(() -> query.get("password")
.orElseThrow(() -> new BadRequestException("'password' parameter not defined"))); .orElseThrow(() -> new BadRequestException("'password' parameter not defined")));
} }
private String getUser(URIQuery form, URIQuery query) { private String getUser(@Untrusted URIQuery form, @Untrusted URIQuery query) {
return form.get("user") return form.get("user")
.orElseGet(() -> query.get("user") .orElseGet(() -> query.get("user")
.orElseThrow(() -> new BadRequestException("'user' parameter not defined"))); .orElseThrow(() -> new BadRequestException("'user' parameter not defined")));

View File

@ -32,6 +32,7 @@ import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionSer
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -88,14 +89,14 @@ public class ExtensionJSONResolver implements Resolver {
) )
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(Request request) {
String identifier = request.getQuery().get("server") @Untrusted String identifier = request.getQuery().get("server")
.orElseThrow(() -> new BadRequestException("'server' parameter was not given")); .orElseThrow(() -> new BadRequestException("'server' parameter was not given"));
ServerUUID serverUUID = identifiers.getServerUUID(identifier) ServerUUID serverUUID = identifiers.getServerUUID(identifier)
.orElseThrow(() -> new NotFoundException("Server with identifier '" + identifier + "' was not found in database")); .orElseThrow(() -> new NotFoundException("Server with given server-parameter was not found in database"));
return Optional.of(getResponse(request, serverUUID)); return Optional.of(getResponse(request, serverUUID));
} }
private JSONStorage.StoredJSON getJSON(Request request, ServerUUID serverUUID) { private JSONStorage.StoredJSON getJSON(@Untrusted Request request, ServerUUID serverUUID) {
Optional<Long> timestamp = Identifiers.getTimestamp(request); Optional<Long> timestamp = Identifiers.getTimestamp(request);
return jsonResolverService.resolve( return jsonResolverService.resolve(

View File

@ -29,6 +29,7 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage; import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -41,7 +42,6 @@ import jakarta.ws.rs.Path;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Collections;
import java.util.Optional; import java.util.Optional;
/** /**
@ -121,7 +121,7 @@ public class GraphsJSONResolver implements Resolver {
} }
private Response getResponse(Request request) { private Response getResponse(Request request) {
String type = request.getQuery().get("type") @Untrusted String type = request.getQuery().get("type")
.orElseThrow(() -> new BadRequestException("'type' parameter was not defined.")); .orElseThrow(() -> new BadRequestException("'type' parameter was not defined."));
DataID dataID = getDataID(type); DataID dataID = getDataID(type);
@ -132,7 +132,7 @@ public class GraphsJSONResolver implements Resolver {
.build(); .build();
} }
private JSONStorage.StoredJSON getGraphJSON(Request request, DataID dataID) { private JSONStorage.StoredJSON getGraphJSON(@Untrusted Request request, DataID dataID) {
Optional<Long> timestamp = Identifiers.getTimestamp(request); Optional<Long> timestamp = Identifiers.getTimestamp(request);
JSONStorage.StoredJSON storedJSON; JSONStorage.StoredJSON storedJSON;
@ -151,7 +151,7 @@ public class GraphsJSONResolver implements Resolver {
return storedJSON; return storedJSON;
} }
private DataID getDataID(String type) { private DataID getDataID(@Untrusted String type) {
switch (type) { switch (type) {
case "performance": case "performance":
return DataID.GRAPH_PERFORMANCE; return DataID.GRAPH_PERFORMANCE;
@ -186,7 +186,7 @@ public class GraphsJSONResolver implements Resolver {
} }
} }
private Object generateGraphDataJSONOfType(DataID id, ServerUUID serverUUID, URIQuery query) { private Object generateGraphDataJSONOfType(DataID id, ServerUUID serverUUID, @Untrusted URIQuery query) {
switch (id) { switch (id) {
case GRAPH_PERFORMANCE: case GRAPH_PERFORMANCE:
return graphJSON.performanceGraphJSON(serverUUID); return graphJSON.performanceGraphJSON(serverUUID);
@ -218,15 +218,15 @@ public class GraphsJSONResolver implements Resolver {
query.get("after").map(Long::parseLong).orElse(0L), query.get("after").map(Long::parseLong).orElse(0L),
query.get("before").map(Long::parseLong).orElse(System.currentTimeMillis()) query.get("before").map(Long::parseLong).orElse(System.currentTimeMillis())
); );
} catch (NumberFormatException e) { } catch (@Untrusted NumberFormatException e) {
throw new BadRequestException("'after' or 'before' is not a epoch millisecond (number) " + e.getMessage()); throw new BadRequestException("'after' or 'before' is not a epoch millisecond (number)");
} }
default: default:
return Collections.singletonMap("error", "Undefined ID: " + id.name()); throw new BadRequestException("Graph type not supported with server-parameter (" + id.name() + ")");
} }
} }
private Object generateGraphDataJSONOfType(DataID id, URIQuery query) { private Object generateGraphDataJSONOfType(DataID id, @Untrusted URIQuery query) {
switch (id) { switch (id) {
case GRAPH_ACTIVITY: case GRAPH_ACTIVITY:
return graphJSON.activityGraphsJSONAsMap(); return graphJSON.activityGraphsJSONAsMap();
@ -246,11 +246,11 @@ public class GraphsJSONResolver implements Resolver {
query.get("after").map(Long::parseLong).orElse(0L), query.get("after").map(Long::parseLong).orElse(0L),
query.get("before").map(Long::parseLong).orElse(System.currentTimeMillis()) query.get("before").map(Long::parseLong).orElse(System.currentTimeMillis())
); );
} catch (NumberFormatException e) { } catch (@Untrusted NumberFormatException e) {
throw new BadRequestException("'after' or 'before' is not a epoch millisecond (number) " + e.getMessage()); throw new BadRequestException("'after' or 'before' is not a epoch millisecond (number)");
} }
default: default:
return Collections.singletonMap("error", "Undefined ID: " + id.name()); throw new BadRequestException("Graph type not supported without server-parameter (" + id.name() + ")");
} }
} }
} }

View File

@ -31,6 +31,7 @@ import com.djrapitops.plan.settings.locale.LocaleSystem;
import com.djrapitops.plan.settings.locale.lang.Lang; import com.djrapitops.plan.settings.locale.lang.Lang;
import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.PlanFiles;
import com.djrapitops.plan.storage.file.Resource; import com.djrapitops.plan.storage.file.Resource;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -96,7 +97,7 @@ public class LocaleJSONResolver implements NoAuthResolver {
private Response getResponse(Request request) { private Response getResponse(Request request) {
ResponseBuilder builder = Response.builder(); ResponseBuilder builder = Response.builder();
Optional<String> langCode = request.getPath().getPart(1); @Untrusted Optional<String> langCode = request.getPath().getPart(1);
Map<String, Object> json = langCode Map<String, Object> json = langCode
.map(this::getLocaleJSON) .map(this::getLocaleJSON)
.orElseGet(this::getLanguageListJSON); .orElseGet(this::getLanguageListJSON);
@ -137,7 +138,7 @@ public class LocaleJSONResolver implements NoAuthResolver {
return json; return json;
} }
private Map<String, Object> getLocaleJSON(String langCode) { private Map<String, Object> getLocaleJSON(@Untrusted String langCode) {
try { try {
LangCode code = LangCode.valueOf(langCode.toUpperCase()); LangCode code = LangCode.valueOf(langCode.toUpperCase());
Map<String, Object> json = new TreeMap<>(); Map<String, Object> json = new TreeMap<>();
@ -153,7 +154,7 @@ public class LocaleJSONResolver implements NoAuthResolver {
} }
return dfs(loadLocale(file), json); return dfs(loadLocale(file), json);
} catch (IllegalArgumentException noSuchEnum) { } catch (@Untrusted IllegalArgumentException noSuchEnum) {
return Collections.emptyMap(); return Collections.emptyMap();
} catch (IOException dfsFileLookupError) { } catch (IOException dfsFileLookupError) {
throw new UncheckedIOException(dfsFileLookupError); throw new UncheckedIOException(dfsFileLookupError);

View File

@ -33,6 +33,7 @@ import com.djrapitops.plan.settings.locale.lang.GenericLang;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.objects.TPSQueries; import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -119,7 +120,7 @@ public class NetworkPerformanceJSONResolver implements Resolver {
.build()); .build());
} }
private List<UUID> getUUIDList(String jsonString) { private List<UUID> getUUIDList(@Untrusted String jsonString) {
return gson.fromJson(jsonString, new TypeToken<List<UUID>>() {}.getType()); return gson.fromJson(jsonString, new TypeToken<List<UUID>>() {}.getType());
} }

View File

@ -27,6 +27,7 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage; import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -100,7 +101,7 @@ public class PlayersTableJSONResolver implements Resolver {
.build(); .build();
} }
private JSONStorage.StoredJSON getStoredJSON(Request request) { private JSONStorage.StoredJSON getStoredJSON(@Untrusted Request request) {
Optional<Long> timestamp = Identifiers.getTimestamp(request); Optional<Long> timestamp = Identifiers.getTimestamp(request);
JSONStorage.StoredJSON storedJSON; JSONStorage.StoredJSON storedJSON;
if (request.getQuery().get("server").isPresent()) { if (request.getQuery().get("server").isPresent()) {

View File

@ -47,6 +47,7 @@ import com.djrapitops.plan.storage.database.queries.filter.QueryFilters;
import com.djrapitops.plan.storage.database.queries.objects.GeoInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.GeoInfoQueries;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries; import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery; import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -131,12 +132,12 @@ public class QueryJSONResolver implements Resolver {
return Optional.of(getResponse(request)); return Optional.of(getResponse(request));
} }
private Response getResponse(Request request) { private Response getResponse(@Untrusted Request request) {
Optional<Response> cachedResult = checkForCachedResult(request); Optional<Response> cachedResult = checkForCachedResult(request);
if (cachedResult.isPresent()) return cachedResult.get(); if (cachedResult.isPresent()) return cachedResult.get();
InputQueryDto inputQuery = parseInputQuery(request); InputQueryDto inputQuery = parseInputQuery(request);
List<InputFilterDto> queries = inputQuery.getFilters(); @Untrusted List<InputFilterDto> queries = inputQuery.getFilters();
Filter.Result result = filters.apply(queries); Filter.Result result = filters.apply(queries);
List<Filter.ResultPath> resultPath = result.getInverseResultPath(); List<Filter.ResultPath> resultPath = result.getInverseResultPath();
@ -145,7 +146,7 @@ public class QueryJSONResolver implements Resolver {
return buildAndStoreResponse(inputQuery, result, resultPath); return buildAndStoreResponse(inputQuery, result, resultPath);
} }
private InputQueryDto parseInputQuery(Request request) { private InputQueryDto parseInputQuery(@Untrusted Request request) {
if (request.getRequestBody().length == 0) { if (request.getRequestBody().length == 0) {
return parseInputQueryFromQueryParams(request); return parseInputQueryFromQueryParams(request);
} else { } else {
@ -153,11 +154,11 @@ public class QueryJSONResolver implements Resolver {
} }
} }
private InputQueryDto parseInputQueryFromQueryParams(Request request) { private InputQueryDto parseInputQueryFromQueryParams(@Untrusted Request request) {
String q = request.getQuery().get("q").orElseThrow(() -> new BadRequestException("'q' parameter not set (expecting json array)")); @Untrusted String q = request.getQuery().get("q").orElseThrow(() -> new BadRequestException("'q' parameter not set (expecting json array)"));
try { try {
String query = URLDecoder.decode(q, StandardCharsets.UTF_8); @Untrusted String query = URLDecoder.decode(q, StandardCharsets.UTF_8);
List<InputFilterDto> queryFilters = InputFilterDto.parse(query, gson); @Untrusted List<InputFilterDto> queryFilters = InputFilterDto.parse(query, gson);
ViewDto view = request.getQuery().get("view") ViewDto view = request.getQuery().get("view")
.map(viewJson -> gson.fromJson(viewJson, ViewDto.class)) .map(viewJson -> gson.fromJson(viewJson, ViewDto.class))
.orElseThrow(() -> new BadRequestException("'view' parameter not set (expecting json object {afterDate, afterTime, beforeDate, beforeTime})")); .orElseThrow(() -> new BadRequestException("'view' parameter not set (expecting json object {afterDate, afterTime, beforeDate, beforeTime})"));
@ -167,15 +168,16 @@ public class QueryJSONResolver implements Resolver {
} }
} }
private Optional<Response> checkForCachedResult(Request request) { private Optional<Response> checkForCachedResult(@Untrusted Request request) {
try { try {
return request.getQuery().get("timestamp") return request.getQuery().get("timestamp")
.flatMap(queryTimestamp -> jsonStorage.fetchExactJson("query", Long.parseLong(queryTimestamp))) .map(Long::parseLong)
.flatMap(queryTimestamp -> jsonStorage.fetchExactJson("query", queryTimestamp))
.map(results -> Response.builder() .map(results -> Response.builder()
.setMimeType(MimeType.JSON) .setMimeType(MimeType.JSON)
.setJSONContent(results.json) .setJSONContent(results.json)
.build()); .build());
} catch (NumberFormatException e) { } catch (@Untrusted NumberFormatException e) {
throw new BadRequestException("Could not parse 'timestamp' into a number. Remove parameter or fix it."); throw new BadRequestException("Could not parse 'timestamp' into a number. Remove parameter or fix it.");
} }
} }
@ -183,10 +185,10 @@ public class QueryJSONResolver implements Resolver {
private Response buildAndStoreResponse(InputQueryDto input, Filter.Result result, List<Filter.ResultPath> resultPath) { private Response buildAndStoreResponse(InputQueryDto input, Filter.Result result, List<Filter.ResultPath> resultPath) {
try { try {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
Map<String, Object> json = Maps.builder(String.class, Object.class) @Untrusted Map<String, Object> json = Maps.builder(String.class, Object.class)
.put("path", resultPath) .put("path", resultPath)
.put("view", input.getView()) .put("view", input.getView())
.put("filters", input.getFilters()) .put("filters", input.getFilters()) // filters json may contain untrusted data
.put("timestamp", timestamp) .put("timestamp", timestamp)
.build(); .build();
if (!result.isEmpty()) { if (!result.isEmpty()) {

View File

@ -24,6 +24,7 @@ import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException; import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException; import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException;
import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -75,7 +76,7 @@ public class ServerIdentityJSONResolver implements Resolver {
) )
@Override @Override
public Optional<Response> resolve(Request request) { public Optional<Response> resolve(Request request) {
String serverIdentifier = request.getQuery().get("server") @Untrusted String serverIdentifier = request.getQuery().get("server")
.orElseThrow(() -> new BadRequestException("Missing 'server' query parameter")); .orElseThrow(() -> new BadRequestException("Missing 'server' query parameter"));
ServerDto server = jsonFactory.serverForIdentifier(serverIdentifier) ServerDto server = jsonFactory.serverForIdentifier(serverIdentifier)
.orElseThrow(() -> new NotFoundException("Server with identifier '" + serverIdentifier + "' was not found in the database")); .orElseThrow(() -> new NotFoundException("Server with identifier '" + serverIdentifier + "' was not found in the database"));

View File

@ -26,6 +26,7 @@ import com.djrapitops.plan.delivery.webserver.cache.AsyncJSONResolverService;
import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@ -62,7 +63,7 @@ public class ServerTabJSONResolver<T> implements Resolver {
return Optional.of(getResponse(request)); return Optional.of(getResponse(request));
} }
private Response getResponse(Request request) { private Response getResponse(@Untrusted Request request) {
ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
return Response.builder() return Response.builder()
.setMimeType(MimeType.JSON) .setMimeType(MimeType.JSON)

View File

@ -27,6 +27,7 @@ import com.djrapitops.plan.delivery.webserver.cache.DataID;
import com.djrapitops.plan.delivery.webserver.cache.JSONStorage; import com.djrapitops.plan.delivery.webserver.cache.JSONStorage;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.identification.ServerUUID; import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.utilities.dev.Untrusted;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
@ -97,7 +98,7 @@ public class SessionsJSONResolver implements Resolver {
.build(); .build();
} }
private JSONStorage.StoredJSON getStoredJSON(Request request) { private JSONStorage.StoredJSON getStoredJSON(@Untrusted Request request) {
Optional<Long> timestamp = Identifiers.getTimestamp(request); Optional<Long> timestamp = Identifiers.getTimestamp(request);
if (request.getQuery().get("server").isPresent()) { if (request.getQuery().get("server").isPresent()) {
ServerUUID serverUUID = identifiers.getServerUUID(request); ServerUUID serverUUID = identifiers.getServerUUID(request);

View File

@ -21,7 +21,7 @@ import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionGroupsTable; import com.djrapitops.plan.storage.database.sql.tables.ExtensionGroupsTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import org.apache.commons.text.TextStringBuilder; import com.djrapitops.plan.utilities.dev.Untrusted;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -38,9 +38,10 @@ public class ExtensionUserIdsInGroupQuery extends QueryStatement<Set<Integer>> {
private final String pluginName; private final String pluginName;
private final String groupProvider; private final String groupProvider;
private final ServerUUID serverUUID; private final ServerUUID serverUUID;
@Untrusted
private final List<String> inGroups; private final List<String> inGroups;
public ExtensionUserIdsInGroupQuery(String pluginName, String groupProvider, ServerUUID serverUUID, List<String> inGroups) { public ExtensionUserIdsInGroupQuery(String pluginName, String groupProvider, ServerUUID serverUUID, @Untrusted List<String> inGroups) {
super(buildSQL(inGroups), 100); super(buildSQL(inGroups), 100);
this.pluginName = pluginName; this.pluginName = pluginName;
this.groupProvider = groupProvider; this.groupProvider = groupProvider;
@ -48,21 +49,19 @@ public class ExtensionUserIdsInGroupQuery extends QueryStatement<Set<Integer>> {
this.inGroups = inGroups; this.inGroups = inGroups;
} }
private static String buildSQL(Collection<String> inGroups) { private static String buildSQL(@Untrusted Collection<String> inGroups) {
TextStringBuilder dynamicInClauseAllocation = new TextStringBuilder();
dynamicInClauseAllocation.appendWithSeparators(inGroups.stream().map(group -> "?").toArray(), ",");
return SELECT + DISTINCT + "u." + UsersTable.ID + return SELECT + DISTINCT + "u." + UsersTable.ID +
FROM + ExtensionGroupsTable.TABLE_NAME + " groups" + FROM + ExtensionGroupsTable.TABLE_NAME + " groups" +
INNER_JOIN + UsersTable.TABLE_NAME + " u on u." + UsersTable.USER_UUID + "=groups." + ExtensionGroupsTable.USER_UUID + INNER_JOIN + UsersTable.TABLE_NAME + " u on u." + UsersTable.USER_UUID + "=groups." + ExtensionGroupsTable.USER_UUID +
WHERE + ExtensionGroupsTable.PROVIDER_ID + "=" + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID + WHERE + ExtensionGroupsTable.PROVIDER_ID + "=" + ExtensionProviderTable.STATEMENT_SELECT_PROVIDER_ID +
AND + ExtensionGroupsTable.GROUP_NAME + " IN (" + dynamicInClauseAllocation.build() + ")"; AND + ExtensionGroupsTable.GROUP_NAME + " IN (" + nParameters(inGroups.size()) + ")";
} }
@Override @Override
public void prepare(PreparedStatement statement) throws SQLException { public void prepare(PreparedStatement statement) throws SQLException {
ExtensionProviderTable.set3PluginValuesToStatement(statement, 1, groupProvider, pluginName, serverUUID); ExtensionProviderTable.set3PluginValuesToStatement(statement, 1, groupProvider, pluginName, serverUUID);
int index = 4; int index = 4;
for (String group : inGroups) { for (@Untrusted String group : inGroups) {
setStringOrNull(statement, index, group == null || "null".equalsIgnoreCase(group) ? null : group); setStringOrNull(statement, index, group == null || "null".equalsIgnoreCase(group) ? null : group);
index++; index++;
} }

View File

@ -196,6 +196,7 @@ public class FinishedSession implements DateHolder {
getExtraData(PlayerKills.class).orElseGet(PlayerKills::new).toJson() + ';' + getExtraData(PlayerKills.class).orElseGet(PlayerKills::new).toJson() + ';' +
getExtraData(MobKillCounter.class).orElseGet(MobKillCounter::new).toJson() + ';' + getExtraData(MobKillCounter.class).orElseGet(MobKillCounter::new).toJson() + ';' +
getExtraData(DeathCounter.class).orElseGet(DeathCounter::new).toJson() + ';' + getExtraData(DeathCounter.class).orElseGet(DeathCounter::new).toJson() + ';' +
// Join address contains @Untrusted data
getExtraData(JoinAddress.class).map(JoinAddress::getAddress).orElse(JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP) + ';' + getExtraData(JoinAddress.class).map(JoinAddress::getAddress).orElse(JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP) + ';' +
getExtraData(PlayerName.class).map(PlayerName::get).orElseGet(playerUUID::toString); getExtraData(PlayerName.class).map(PlayerName::get).orElseGet(playerUUID::toString);
} }

View File

@ -17,11 +17,13 @@
package com.djrapitops.plan.gathering.domain.event; package com.djrapitops.plan.gathering.domain.event;
import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable; import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
@Untrusted
public class JoinAddress { public class JoinAddress {
private final Supplier<String> address; private final Supplier<String> address;
@ -33,6 +35,7 @@ public class JoinAddress {
this.address = address; this.address = address;
} }
@Untrusted
public String getAddress() { public String getAddress() {
return StringUtils.truncate(address.get(), JoinAddressTable.JOIN_ADDRESS_MAX_LENGTH); return StringUtils.truncate(address.get(), JoinAddressTable.JOIN_ADDRESS_MAX_LENGTH);
} }

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.gathering.importing;
import com.djrapitops.plan.SubSystem; import com.djrapitops.plan.SubSystem;
import com.djrapitops.plan.gathering.importing.importers.Importer; import com.djrapitops.plan.gathering.importing.importers.Importer;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -53,7 +54,7 @@ public class ImportSystem implements SubSystem {
importers.put(importer.getName(), importer); importers.put(importer.getName(), importer);
} }
public Optional<Importer> getImporter(String name) { public Optional<Importer> getImporter(@Untrusted String name) {
return Optional.ofNullable(importers.get(name)); return Optional.ofNullable(importers.get(name));
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries; import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
@ -63,55 +64,7 @@ public class Identifiers {
)); ));
} }
/** public static Optional<Long> getTimestamp(@Untrusted Request request) {
* Obtain UUID of the server.
*
* @param identifier Identifier (name or uuid string) of the server
* @return UUID of the server.
* @throws BadRequestException If the server is not in the database.
*/
public Optional<ServerUUID> getServerUUID(String identifier) {
Optional<ServerUUID> parsed = UUIDUtility.parseFromString(identifier).map(ServerUUID::from);
if (parsed.isPresent()) return parsed;
return getServerUUIDFromName(identifier);
}
private Optional<ServerUUID> getServerUUIDFromName(String serverName) {
return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverName))
.map(Server::getUuid);
}
/**
* Obtain UUID of the player.
*
* @param request for Request, URIQuery needs a 'player' parameter.
* @return UUID of the player.
* @throws BadRequestException If player parameter is not defined or the player is not in the database.
*/
public UUID getPlayerUUID(Request request) {
String playerIdentifier = request.getQuery().get("player")
.orElseThrow(() -> new BadRequestException("'player' parameter was not defined.")).trim();
Optional<UUID> parsed = UUIDUtility.parseFromString(playerIdentifier);
return parsed.orElseGet(() -> getPlayerUUIDFromName(playerIdentifier));
}
private UUID getPlayerUUIDFromName(String playerName) {
return dbSystem.getDatabase()
.query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName))
.orElseThrow(() -> new BadRequestException("Given 'player' was not found in the database."));
}
@Nullable
public UUID getPlayerUUID(String name) {
return uuidUtility.getUUIDOf(name);
}
public Optional<Integer> getPlayerUserId(UUID playerUUID) {
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchUserId(playerUUID));
}
public static Optional<Long> getTimestamp(Request request) {
try { try {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long timestamp = request.getQuery().get("timestamp") long timestamp = request.getQuery().get("timestamp")
@ -125,4 +78,52 @@ public class Identifiers {
throw new BadRequestException("'timestamp' was not a number: " + nonNumberTimestamp.getMessage()); throw new BadRequestException("'timestamp' was not a number: " + nonNumberTimestamp.getMessage());
} }
} }
/**
* Obtain UUID of the server.
*
* @param identifier Identifier (name or uuid string) of the server
* @return UUID of the server.
* @throws BadRequestException If the server is not in the database.
*/
public Optional<ServerUUID> getServerUUID(@Untrusted String identifier) {
Optional<ServerUUID> parsed = UUIDUtility.parseFromString(identifier).map(ServerUUID::from);
if (parsed.isPresent()) return parsed;
return getServerUUIDFromName(identifier);
}
private Optional<ServerUUID> getServerUUIDFromName(@Untrusted String serverName) {
return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverName))
.map(Server::getUuid);
}
/**
* Obtain UUID of the player.
*
* @param request for Request, URIQuery needs a 'player' parameter.
* @return UUID of the player.
* @throws BadRequestException If player parameter is not defined or the player is not in the database.
*/
public UUID getPlayerUUID(@Untrusted Request request) {
@Untrusted String playerIdentifier = request.getQuery().get("player")
.orElseThrow(() -> new BadRequestException("'player' parameter was not defined.")).trim();
Optional<UUID> parsed = UUIDUtility.parseFromString(playerIdentifier);
return parsed.orElseGet(() -> getPlayerUUIDFromName(playerIdentifier));
}
@Nullable
public UUID getPlayerUUID(String name) {
return uuidUtility.getUUIDOf(name);
}
public Optional<Integer> getPlayerUserId(UUID playerUUID) {
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchUserId(playerUUID));
}
private UUID getPlayerUUIDFromName(@Untrusted String playerName) {
return dbSystem.getDatabase()
.query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName))
.orElseThrow(() -> new BadRequestException("Given 'player' was not found in the database."));
}
} }

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.identification;
import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.exceptions.database.DBOpException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries; import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
import net.playeranalytics.plugin.player.UUIDFetcher; import net.playeranalytics.plugin.player.UUIDFetcher;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -50,18 +51,18 @@ public class UUIDUtility {
this.errorLogger = errorLogger; this.errorLogger = errorLogger;
} }
public static Optional<UUID> parseFromString(String uuidString) { public static Optional<UUID> parseFromString(@Untrusted String uuidString) {
try { try {
return Optional.of(UUID.fromString(uuidString)); return Optional.of(UUID.fromString(uuidString));
} catch (IllegalArgumentException malformedUUIDException) { } catch (@Untrusted IllegalArgumentException malformedUUIDException) {
return Optional.empty(); return Optional.empty();
} }
} }
public Optional<String> getNameOf(String possiblePlayerUUID) { public Optional<String> getNameOf(@Untrusted String possiblePlayerUUID) {
try { try {
return getNameOf(UUID.fromString(possiblePlayerUUID)); return getNameOf(UUID.fromString(possiblePlayerUUID));
} catch (IllegalArgumentException notUUID) { } catch (@Untrusted IllegalArgumentException notUUID) {
return Optional.empty(); return Optional.empty();
} }
} }
@ -78,7 +79,7 @@ public class UUIDUtility {
* @return UUID of the player * @return UUID of the player
*/ */
@Nullable @Nullable
public UUID getUUIDOf(String playerName) { public UUID getUUIDOf(@Untrusted String playerName) {
if (playerName == null) throw new IllegalArgumentException("Player name can not be null!"); if (playerName == null) throw new IllegalArgumentException("Player name can not be null!");
UUID uuid = getUUIDFromString(playerName); UUID uuid = getUUIDFromString(playerName);
if (uuid != null) return uuid; if (uuid != null) return uuid;
@ -87,23 +88,23 @@ public class UUIDUtility {
.orElse(getUUIDViaUUIDFetcher(playerName)); .orElse(getUUIDViaUUIDFetcher(playerName));
} }
private UUID getUUIDFromString(String playerName) { private UUID getUUIDFromString(@Untrusted String playerName) {
try { try {
return UUID.fromString(playerName); return UUID.fromString(playerName);
} catch (IllegalArgumentException ignore) { } catch (@Untrusted IllegalArgumentException ignore) {
return null; return null;
} }
} }
private UUID getUUIDViaUUIDFetcher(String playerName) { private UUID getUUIDViaUUIDFetcher(@Untrusted String playerName) {
try { try {
return UUIDFetcher.getUUIDOf(playerName); return UUIDFetcher.getUUIDOf(playerName);
} catch (Exception | NoClassDefFoundError ignored) { } catch (@Untrusted Exception | NoClassDefFoundError ignored) {
return null; return null;
} }
} }
private Optional<UUID> getUUIDFromDB(String playerName) { private Optional<UUID> getUUIDFromDB(@Untrusted String playerName) {
try { try {
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName)); return dbSystem.getDatabase().query(UserIdentifierQueries.fetchPlayerUUIDOf(playerName));
} catch (DBOpException e) { } catch (DBOpException e) {

View File

@ -23,6 +23,7 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries; import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -54,11 +55,11 @@ public class OperatorPlaceholders implements Placeholders {
); );
} }
private ServerUUID getServerUUID(Arguments parameters) { private ServerUUID getServerUUID(@Untrusted Arguments parameters) {
return parameters.get(0).flatMap(this::getServerUUIDForServerIdentifier).orElseGet(serverInfo::getServerUUID); return parameters.get(0).flatMap(this::getServerUUIDForServerIdentifier).orElseGet(serverInfo::getServerUUID);
} }
private Optional<ServerUUID> getServerUUIDForServerIdentifier(String serverIdentifier) { private Optional<ServerUUID> getServerUUIDForServerIdentifier(@Untrusted String serverIdentifier) {
return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier)) return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier))
.map(Server::getUuid); .map(Server::getUuid);
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
import com.djrapitops.plan.identification.Identifiers; import com.djrapitops.plan.identification.Identifiers;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries; import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -107,21 +108,21 @@ public final class PlanPlaceholders {
* value found but the placeholder is registered, * value found but the placeholder is registered,
* otherwise {@code null} * otherwise {@code null}
*/ */
public String onPlaceholderRequest(UUID uuid, String placeholder, List<String> parameters) { public String onPlaceholderRequest(UUID uuid, @Untrusted String placeholder, @Untrusted List<String> parameters) {
for (Entry<String, Function<String, Serializable>> entry : rawHandlers.entrySet()) { for (Entry<String, Function<String, Serializable>> entry : rawHandlers.entrySet()) {
if (placeholder.startsWith(entry.getKey())) { if (placeholder.startsWith(entry.getKey())) {
return Objects.toString(entry.getValue().apply(placeholder)); return Objects.toString(entry.getValue().apply(placeholder));
} }
} }
Arguments arguments = new Arguments(parameters); @Untrusted Arguments arguments = new Arguments(parameters);
StaticPlaceholderLoader staticLoader = staticPlaceholders.get(placeholder); StaticPlaceholderLoader staticLoader = staticPlaceholders.get(placeholder);
if (staticLoader != null) { if (staticLoader != null) {
return Objects.toString(staticLoader.apply(arguments)); return Objects.toString(staticLoader.apply(arguments));
} }
Optional<String> givenIdentifier = arguments.get(0); @Untrusted Optional<String> givenIdentifier = arguments.get(0);
Optional<UUID> foundUUID = givenIdentifier Optional<UUID> foundUUID = givenIdentifier
.flatMap(this::getPlayerUUIDForIdentifier); .flatMap(this::getPlayerUUIDForIdentifier);
UUID playerUUID = foundUUID.orElse(uuid); UUID playerUUID = foundUUID.orElse(uuid);
@ -142,7 +143,7 @@ public final class PlanPlaceholders {
return null; return null;
} }
private Optional<UUID> getPlayerUUIDForIdentifier(String identifier) { private Optional<UUID> getPlayerUUIDForIdentifier(@Untrusted String identifier) {
return Optional.ofNullable(identifiers.getPlayerUUID(identifier)); return Optional.ofNullable(identifiers.getPlayerUUID(identifier));
} }

View File

@ -29,6 +29,7 @@ import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
import com.djrapitops.plan.storage.database.queries.analysis.TopListQueries; import com.djrapitops.plan.storage.database.queries.analysis.TopListQueries;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.TPSQueries; import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -201,11 +202,11 @@ public class ServerPlaceHolders implements Placeholders {
registerDynamicCategoryPlaceholders(placeholders, database); registerDynamicCategoryPlaceholders(placeholders, database);
} }
private ServerUUID getServerUUID(Arguments parameters) { private ServerUUID getServerUUID(@Untrusted Arguments parameters) {
return parameters.get(0).flatMap(this::getServerUUIDForServerIdentifier).orElseGet(serverInfo::getServerUUID); return parameters.get(0).flatMap(this::getServerUUIDForServerIdentifier).orElseGet(serverInfo::getServerUUID);
} }
private Optional<ServerUUID> getServerUUIDForServerIdentifier(String serverIdentifier) { private Optional<ServerUUID> getServerUUIDForServerIdentifier(@Untrusted String serverIdentifier) {
return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier)) return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier))
.map(Server::getUuid); .map(Server::getUuid);
} }
@ -242,7 +243,7 @@ public class ServerPlaceHolders implements Placeholders {
} }
interface QueryCreator<T> { interface QueryCreator<T> {
Query<Optional<TopListQueries.TopListEntry<T>>> apply(Integer number, Long timespan, Arguments parameters); Query<Optional<TopListQueries.TopListEntry<T>>> apply(Integer number, Long timespan, @Untrusted Arguments parameters);
} }
public static class TopCategoryQuery<T> { public static class TopCategoryQuery<T> {
@ -266,7 +267,7 @@ public class ServerPlaceHolders implements Placeholders {
return timeSpan; return timeSpan;
} }
public Query<Optional<TopListQueries.TopListEntry<T>>> getQuery(int i, Arguments parameters) { public Query<Optional<TopListQueries.TopListEntry<T>>> getQuery(int i, @Untrusted Arguments parameters) {
return queryCreator.apply(i, timeSpanMillis, parameters); return queryCreator.apply(i, timeSpanMillis, parameters);
} }
} }

View File

@ -29,6 +29,7 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries; import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
import com.djrapitops.plan.storage.database.queries.objects.*; import com.djrapitops.plan.storage.database.queries.objects.*;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -219,13 +220,13 @@ public class SessionPlaceHolders implements Placeholders {
parameters -> database.query(TPSQueries.fetchPeakPlayerCount(getServerUUID(parameters), now() - TimeUnit.DAYS.toMillis(2L))).map(year).orElse("-")); parameters -> database.query(TPSQueries.fetchPeakPlayerCount(getServerUUID(parameters), now() - TimeUnit.DAYS.toMillis(2L))).map(year).orElse("-"));
} }
private ServerUUID getServerUUID(Arguments parameters) { private ServerUUID getServerUUID(@Untrusted Arguments parameters) {
return parameters.get(0) return parameters.get(0)
.flatMap(this::getServerUUIDForServerIdentifier) .flatMap(this::getServerUUIDForServerIdentifier)
.orElseGet(serverInfo::getServerUUID); .orElseGet(serverInfo::getServerUUID);
} }
private Optional<ServerUUID> getServerUUIDForServerIdentifier(String serverIdentifier) { private Optional<ServerUUID> getServerUUIDForServerIdentifier(@Untrusted String serverIdentifier) {
return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier)) return dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverIdentifier))
.map(Server::getUuid); .map(Server::getUuid);
} }

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.storage.database; package com.djrapitops.plan.storage.database;
import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -80,7 +81,7 @@ public enum DBType {
* @param name the name of the {@code DBType} * @param name the name of the {@code DBType}
* @return an {@code Optional<DBType>} * @return an {@code Optional<DBType>}
*/ */
public static Optional<DBType> getForName(String name) { public static Optional<DBType> getForName(@Untrusted String name) {
for (DBType dbType : DBType.values()) { for (DBType dbType : DBType.values()) {
if (dbType.getName().equalsIgnoreCase(name)) { if (dbType.getName().equalsIgnoreCase(name)) {
return Optional.of(dbType); return Optional.of(dbType);

View File

@ -24,7 +24,7 @@ import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable; import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable; import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.utilities.Benchmark; import com.djrapitops.plan.utilities.dev.Benchmark;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.storage.database.queries.filter; package com.djrapitops.plan.storage.database.queries.filter;
import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto; import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.util.*; import java.util.*;
@ -42,9 +43,9 @@ public interface Filter {
* @return Set of UUIDs this filter applies to * @return Set of UUIDs this filter applies to
* @throws IllegalArgumentException If the arguments are not valid. * @throws IllegalArgumentException If the arguments are not valid.
*/ */
Set<Integer> getMatchingUserIds(InputFilterDto query); Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query);
default Result apply(InputFilterDto query) { default Result apply(@Untrusted InputFilterDto query) {
try { try {
return new Result(null, getKind(), getMatchingUserIds(query)); return new Result(null, getKind(), getMatchingUserIds(query));
} catch (CompleteSetException allMatch) { } catch (CompleteSetException allMatch) {

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.filters.AllPlayersFilter; import com.djrapitops.plan.storage.database.queries.filter.filters.AllPlayersFilter;
import com.djrapitops.plan.storage.database.queries.filter.filters.PluginGroupsFilter; import com.djrapitops.plan.storage.database.queries.filter.filters.PluginGroupsFilter;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -70,7 +71,7 @@ public class QueryFilters {
} }
} }
public Optional<Filter> getFilter(String kind) { public Optional<Filter> getFilter(@Untrusted String kind) {
prepareFilters(); prepareFilters();
return Optional.ofNullable(filters.get(kind)); return Optional.ofNullable(filters.get(kind));
} }
@ -82,25 +83,25 @@ public class QueryFilters {
* @return the result object or null if none of the filterQueries could be applied. * @return the result object or null if none of the filterQueries could be applied.
* @throws BadRequestException If the request kind is not supported or if filter was given bad options. * @throws BadRequestException If the request kind is not supported or if filter was given bad options.
*/ */
public Filter.Result apply(List<InputFilterDto> filterQueries) { public Filter.Result apply(@Untrusted List<InputFilterDto> filterQueries) {
prepareFilters(); prepareFilters();
Filter.Result current = null; Filter.Result current = null;
if (filterQueries.isEmpty()) return allPlayersFilter.apply(null); if (filterQueries.isEmpty()) return allPlayersFilter.apply(null);
for (InputFilterDto inputFilterDto : filterQueries) { for (@Untrusted InputFilterDto inputFilterDto : filterQueries) {
current = apply(current, inputFilterDto); current = apply(current, inputFilterDto);
if (current != null && current.isEmpty()) break; if (current != null && current.isEmpty()) break;
} }
return current; return current;
} }
private Filter.Result apply(Filter.Result current, InputFilterDto inputFilterDto) { private Filter.Result apply(Filter.Result current, @Untrusted InputFilterDto inputFilterDto) {
String kind = inputFilterDto.getKind(); @Untrusted String kind = inputFilterDto.getKind();
Filter filter = getFilter(kind).orElseThrow(() -> new BadRequestException("Filter kind not supported: '" + kind + "'")); Filter filter = getFilter(kind).orElseThrow(() -> new BadRequestException("Filter kind not supported: '" + kind + "'"));
return getResult(current, filter, inputFilterDto); return getResult(current, filter, inputFilterDto);
} }
private Filter.Result getResult(Filter.Result current, Filter filter, InputFilterDto query) { private Filter.Result getResult(Filter.Result current, Filter filter, @Untrusted InputFilterDto query) {
try { try {
return current == null ? filter.apply(query) : current.apply(filter, query); return current == null ? filter.apply(query) : current.apply(filter, query);
} catch (IllegalArgumentException badOptions) { } catch (IllegalArgumentException badOptions) {

View File

@ -24,6 +24,7 @@ import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.analysis.NetworkActivityIndexQueries; import com.djrapitops.plan.storage.database.queries.analysis.NetworkActivityIndexQueries;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException; import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -66,8 +67,8 @@ public class ActivityIndexFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
List<String> selected = getSelected(query); @Untrusted List<String> selected = getSelected(query);
String[] options = getOptionsArray(); String[] options = getOptionsArray();
boolean includeVeryActive = selected.contains(options[0]); boolean includeVeryActive = selected.contains(options[0]);

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.Filter; import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries; import com.djrapitops.plan.storage.database.queries.objects.UserIdentifierQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -51,7 +52,7 @@ public class AllPlayersFilter implements Filter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchAllUserIds()); return dbSystem.getDatabase().query(UserIdentifierQueries.fetchAllUserIds());
} }
} }

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.settings.locale.lang.FilterLang;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException; import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -57,8 +58,8 @@ public class BannedFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
List<String> selected = getSelected(query); @Untrusted List<String> selected = getSelected(query);
Set<Integer> userIds = new HashSet<>(); Set<Integer> userIds = new HashSet<>();
String[] options = getOptionsArray(); String[] options = getOptionsArray();

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.Filter; import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries; import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -61,17 +62,17 @@ public abstract class DateRangeFilter implements Filter {
.build(); .build();
} }
protected long getAfter(InputFilterDto query) { protected long getAfter(@Untrusted InputFilterDto query) {
return getTime(query, "afterDate", "afterTime"); return getTime(query, "afterDate", "afterTime");
} }
protected long getBefore(InputFilterDto query) { protected long getBefore(@Untrusted InputFilterDto query) {
return getTime(query, "beforeDate", "beforeTime"); return getTime(query, "beforeDate", "beforeTime");
} }
private long getTime(InputFilterDto query, String dateKey, String timeKey) { private long getTime(@Untrusted InputFilterDto query, String dateKey, String timeKey) {
String date = query.get(dateKey).orElseThrow(() -> new BadRequestException("'" + dateKey + "' not specified in parameters for " + getKind())); @Untrusted String date = query.get(dateKey).orElseThrow(() -> new BadRequestException("'" + dateKey + "' not specified in parameters for " + getKind()));
String time = query.get(timeKey).orElseThrow(() -> new BadRequestException("'" + timeKey + "' not specified in parameters for " + getKind())); @Untrusted String time = query.get(timeKey).orElseThrow(() -> new BadRequestException("'" + timeKey + "' not specified in parameters for " + getKind()));
try { try {
return dateFormat.parse(date + ' ' + time).getTime(); return dateFormat.parse(date + ' ' + time).getTime();

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database.queries.filter.filters;
import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto; import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.GeoInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.GeoInfoQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -50,7 +51,7 @@ public class GeolocationsFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
return dbSystem.getDatabase().query(GeoInfoQueries.userIdsOfPlayersWithGeolocations(getSelected(query))); return dbSystem.getDatabase().query(GeoInfoQueries.userIdsOfPlayersWithGeolocations(getSelected(query)));
} }
} }

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database.queries.filter.filters;
import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto; import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.JoinAddressQueries; import com.djrapitops.plan.storage.database.queries.objects.JoinAddressQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -50,7 +51,7 @@ public class JoinAddressFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
return dbSystem.getDatabase().query(JoinAddressQueries.userIdsOfPlayersWithJoinAddresses(getSelected(query))); return dbSystem.getDatabase().query(JoinAddressQueries.userIdsOfPlayersWithJoinAddresses(getSelected(query)));
} }
} }

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database.queries.filter.filters;
import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto; import com.djrapitops.plan.delivery.domain.datatransfer.InputFilterDto;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException; import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.filter.Filter; import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -31,9 +32,9 @@ public abstract class MultiOptionFilter implements Filter {
return new String[]{"selected"}; return new String[]{"selected"};
} }
protected List<String> getSelected(InputFilterDto query) { protected List<String> getSelected(@Untrusted InputFilterDto query) {
String selectedJSON = query.get("selected").orElseThrow(IllegalArgumentException::new); @Untrusted String selectedJSON = query.get("selected").orElseThrow(IllegalArgumentException::new);
List<String> selected = new Gson().fromJson(selectedJSON, new TypeToken<List<String>>() {}.getType()); @Untrusted List<String> selected = new Gson().fromJson(selectedJSON, new TypeToken<List<String>>() {}.getType());
if (selected.isEmpty()) throw new CompleteSetException(); if (selected.isEmpty()) throw new CompleteSetException();
return selected; return selected;
} }

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.settings.locale.lang.FilterLang;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException; import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -57,8 +58,8 @@ public class OperatorsFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
List<String> selected = getSelected(query); @Untrusted List<String> selected = getSelected(query);
Set<Integer> userIds = new HashSet<>(); Set<Integer> userIds = new HashSet<>();
String[] options = getOptionsArray(); String[] options = getOptionsArray();

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries; import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import javax.inject.Inject; import javax.inject.Inject;
@ -47,10 +48,10 @@ public class PlayedBetweenDateRangeFilter extends DateRangeFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
long after = getAfter(query); long after = getAfter(query);
long before = getBefore(query); long before = getBefore(query);
List<String> serverNames = getServerNames(query); @Untrusted List<String> serverNames = getServerNames(query);
List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames)); List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames));
return dbSystem.getDatabase().query(SessionQueries.userIdsOfPlayedBetween(after, before, serverUUIDs)); return dbSystem.getDatabase().query(SessionQueries.userIdsOfPlayedBetween(after, before, serverUUIDs));
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -54,8 +55,8 @@ public class PlayedOnServerFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
List<String> serverNames = getSelected(query); @Untrusted List<String> serverNames = getSelected(query);
List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames)); List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames));
return dbSystem.getDatabase().query(UserInfoQueries.userIdsOfRegisteredBetween(0, System.currentTimeMillis(), serverUUIDs)); return dbSystem.getDatabase().query(UserInfoQueries.userIdsOfRegisteredBetween(0, System.currentTimeMillis(), serverUUIDs));

View File

@ -26,7 +26,9 @@ import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
import com.djrapitops.plan.storage.database.queries.QueryStatement; import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.sql.tables.*; import com.djrapitops.plan.storage.database.sql.tables.*;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -81,13 +83,13 @@ public class PluginBooleanGroupFilter extends MultiOptionFilter {
} }
private static Query<Set<Integer>> playersInGroups( private static Query<Set<Integer>> playersInGroups(
Map<PluginBooleanOption, SelectedBoolean> selected, @Untrusted Map<PluginBooleanOption, SelectedBoolean> selected,
Map<String, ServerUUID> namesToUUIDs Map<String, ServerUUID> namesToUUIDs
) { ) {
return db -> { return db -> {
Set<Integer> userIds = new HashSet<>(); Set<Integer> userIds = new HashSet<>();
for (Map.Entry<PluginBooleanOption, SelectedBoolean> option : selected.entrySet()) { for (Map.Entry<PluginBooleanOption, SelectedBoolean> option : selected.entrySet()) {
PluginBooleanOption pluginBooleanOption = option.getKey(); @Untrusted PluginBooleanOption pluginBooleanOption = option.getKey();
SelectedBoolean selectedBoolean = option.getValue(); SelectedBoolean selectedBoolean = option.getValue();
userIds.addAll( userIds.addAll(
db.query(playersInGroup( db.query(playersInGroup(
@ -103,8 +105,12 @@ public class PluginBooleanGroupFilter extends MultiOptionFilter {
} }
private static Query<Set<Integer>> playersInGroup( private static Query<Set<Integer>> playersInGroup(
ServerUUID serverUUID, String pluginName, String providerText, SelectedBoolean selectedBoolean @Nullable ServerUUID serverUUID, @Untrusted String pluginName, @Untrusted String providerText, SelectedBoolean selectedBoolean
) { ) {
if (serverUUID == null) {
return db -> Collections.emptySet();
}
String selectUUIDsWithBooleanValues = SELECT + DISTINCT + "u." + UsersTable.ID + " as id" + String selectUUIDsWithBooleanValues = SELECT + DISTINCT + "u." + UsersTable.ID + " as id" +
FROM + ExtensionPluginTable.TABLE_NAME + " plugin" + FROM + ExtensionPluginTable.TABLE_NAME + " plugin" +
INNER_JOIN + ExtensionProviderTable.TABLE_NAME + " provider on provider." + ExtensionProviderTable.PLUGIN_ID + "=plugin." + ExtensionPluginTable.ID + INNER_JOIN + ExtensionProviderTable.TABLE_NAME + " provider on provider." + ExtensionProviderTable.PLUGIN_ID + "=plugin." + ExtensionPluginTable.ID +
@ -162,12 +168,12 @@ public class PluginBooleanGroupFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
Map<PluginBooleanOption, SelectedBoolean> selectedBooleanOptions = new HashMap<>(); @Untrusted Map<PluginBooleanOption, SelectedBoolean> selectedBooleanOptions = new HashMap<>();
for (String selected : getSelected(query)) { for (@Untrusted String selected : getSelected(query)) {
String[] optionAndBoolean = StringUtils.split(selected, ":", 2); @Untrusted String[] optionAndBoolean = StringUtils.split(selected, ":", 2);
PluginBooleanOption pluginBooleanOption = PluginBooleanOption.parse(optionAndBoolean[0].trim()); @Untrusted PluginBooleanOption pluginBooleanOption = PluginBooleanOption.parse(optionAndBoolean[0].trim());
String selectedBoolean = optionAndBoolean[1].trim().toUpperCase(); @Untrusted String selectedBoolean = optionAndBoolean[1].trim().toUpperCase();
selectedBooleanOptions.computeIfPresent(pluginBooleanOption, (key, existing) -> SelectedBoolean.BOTH); selectedBooleanOptions.computeIfPresent(pluginBooleanOption, (key, existing) -> SelectedBoolean.BOTH);
selectedBooleanOptions.computeIfAbsent(pluginBooleanOption, key -> SelectedBoolean.valueOf(selectedBoolean)); selectedBooleanOptions.computeIfAbsent(pluginBooleanOption, key -> SelectedBoolean.valueOf(selectedBoolean));
} }
@ -183,6 +189,7 @@ public class PluginBooleanGroupFilter extends MultiOptionFilter {
BOTH BOTH
} }
@Untrusted
public static class PluginBooleanOption implements Comparable<PluginBooleanOption> { public static class PluginBooleanOption implements Comparable<PluginBooleanOption> {
private final String serverName; private final String serverName;
private final String pluginName; private final String pluginName;
@ -194,12 +201,13 @@ public class PluginBooleanGroupFilter extends MultiOptionFilter {
this.providerText = providerText; this.providerText = providerText;
} }
public static PluginBooleanOption parse(String fromFormatted) { @Untrusted
String[] split1 = StringUtils.split(fromFormatted, ",", 2); public static PluginBooleanOption parse(@Untrusted String fromFormatted) {
String[] split2 = StringUtils.split(split1[1], "-", 2); @Untrusted String[] split1 = StringUtils.split(fromFormatted, ",", 2);
String serverName = split1[0].trim(); @Untrusted String[] split2 = StringUtils.split(split1[1], "-", 2);
String pluginName = split2[0].trim(); @Untrusted String serverName = split1[0].trim();
String providerName = split2[1].trim(); @Untrusted String pluginName = split2[0].trim();
@Untrusted String providerName = split2[1].trim();
return new PluginBooleanOption(serverName, pluginName, providerName); return new PluginBooleanOption(serverName, pluginName, providerName);
} }

View File

@ -28,6 +28,7 @@ import com.djrapitops.plan.storage.database.sql.tables.ExtensionGroupsTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionPluginTable; import com.djrapitops.plan.storage.database.sql.tables.ExtensionPluginTable;
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable; import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import javax.inject.Inject; import javax.inject.Inject;
@ -67,7 +68,7 @@ public class PluginGroupsFilter extends MultiOptionFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
return dbSystem.getDatabase().query( return dbSystem.getDatabase().query(
new ExtensionUserIdsInGroupQuery(identifier.getPluginName(), identifier.getProviderName(), identifier.getServerUUID(), getSelected(query)) new ExtensionUserIdsInGroupQuery(identifier.getPluginName(), identifier.getProviderName(), identifier.getServerUUID(), getSelected(query))
); );

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries; import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries; import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.google.gson.Gson; import com.google.gson.Gson;
import javax.inject.Inject; import javax.inject.Inject;
@ -48,10 +49,10 @@ public class RegisteredBetweenDateRangeFilter extends DateRangeFilter {
} }
@Override @Override
public Set<Integer> getMatchingUserIds(InputFilterDto query) { public Set<Integer> getMatchingUserIds(@Untrusted InputFilterDto query) {
long after = getAfter(query); long after = getAfter(query);
long before = getBefore(query); long before = getBefore(query);
List<String> serverNames = getServerNames(query); @Untrusted List<String> serverNames = getServerNames(query);
List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames)); List<ServerUUID> serverUUIDs = serverNames.isEmpty() ? Collections.emptyList() : dbSystem.getDatabase().query(ServerQueries.fetchServersMatchingIdentifiers(serverNames));
return dbSystem.getDatabase().query( return dbSystem.getDatabase().query(
serverUUIDs.isEmpty() ? BaseUserQueries.userIdsOfRegisteredBetween(after, before) serverUUIDs.isEmpty() ? BaseUserQueries.userIdsOfRegisteredBetween(after, before)
@ -59,7 +60,7 @@ public class RegisteredBetweenDateRangeFilter extends DateRangeFilter {
); );
} }
private List<String> getServerNames(InputFilterDto query) { private List<String> getServerNames(@Untrusted InputFilterDto query) {
return query.get("servers") return query.get("servers")
.map(serversList -> new Gson().fromJson(serversList, String[].class)) .map(serversList -> new Gson().fromJson(serversList, String[].class))
.map(Arrays::asList) .map(Arrays::asList)

View File

@ -21,10 +21,12 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.queries.QueryAllStatement; import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
import com.djrapitops.plan.storage.database.queries.RowExtractors; import com.djrapitops.plan.storage.database.queries.RowExtractors;
import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable; import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable; import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Lists; import com.djrapitops.plan.utilities.java.Lists;
import org.apache.commons.text.TextStringBuilder; import org.apache.commons.text.TextStringBuilder;
@ -166,14 +168,12 @@ public class GeoInfoQueries {
return db -> db.queryList(sql, RowExtractors.getString(GeoInfoTable.GEOLOCATION)); return db -> db.queryList(sql, RowExtractors.getString(GeoInfoTable.GEOLOCATION));
} }
public static Query<Set<Integer>> userIdsOfPlayersWithGeolocations(List<String> selected) { public static Query<Set<Integer>> userIdsOfPlayersWithGeolocations(@Untrusted List<String> selected) {
String sql = SELECT + "u." + UsersTable.ID + String sql = SELECT + "u." + UsersTable.ID +
FROM + GeoInfoTable.TABLE_NAME + " g" + FROM + GeoInfoTable.TABLE_NAME + " g" +
INNER_JOIN + UsersTable.TABLE_NAME + " u on u.id=g." + GeoInfoTable.USER_ID + INNER_JOIN + UsersTable.TABLE_NAME + " u on u.id=g." + GeoInfoTable.USER_ID +
WHERE + GeoInfoTable.GEOLOCATION + WHERE + GeoInfoTable.GEOLOCATION +
" IN ('" + " IN (" + Sql.nParameters(selected.size()) + ")";
new TextStringBuilder().appendWithSeparators(selected, "','") + return db -> db.querySet(sql, RowExtractors.getInt(UsersTable.ID), selected);
"')";
return db -> db.querySet(sql, RowExtractors.getInt(UsersTable.ID));
} }
} }

View File

@ -26,7 +26,7 @@ import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable; import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable; import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
import org.apache.commons.text.TextStringBuilder; import com.djrapitops.plan.utilities.dev.Untrusted;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -104,12 +104,12 @@ public class JoinAddressQueries {
}; };
} }
public static Query<Set<Integer>> userIdsOfPlayersWithJoinAddresses(List<String> joinAddresses) { public static Query<Set<Integer>> userIdsOfPlayersWithJoinAddresses(@Untrusted List<String> joinAddresses) {
String sql = SELECT + DISTINCT + SessionsTable.USER_ID + String sql = SELECT + DISTINCT + SessionsTable.USER_ID +
FROM + JoinAddressTable.TABLE_NAME + " j" + FROM + JoinAddressTable.TABLE_NAME + " j" +
INNER_JOIN + SessionsTable.TABLE_NAME + " s on s." + SessionsTable.JOIN_ADDRESS_ID + "=j." + JoinAddressTable.ID + INNER_JOIN + SessionsTable.TABLE_NAME + " s on s." + SessionsTable.JOIN_ADDRESS_ID + "=j." + JoinAddressTable.ID +
WHERE + JoinAddressTable.JOIN_ADDRESS + " IN (" + WHERE + JoinAddressTable.JOIN_ADDRESS + " IN (" +
new TextStringBuilder().appendWithSeparators(joinAddresses.stream().map(item -> '?').iterator(), ",") + nParameters(joinAddresses.size()) +
')'; // Don't append addresses directly, SQL injection hazard ')'; // Don't append addresses directly, SQL injection hazard
return db -> db.querySet(sql, RowExtractors.getInt(SessionsTable.USER_ID), joinAddresses.toArray()); return db -> db.querySet(sql, RowExtractors.getInt(SessionsTable.USER_ID), joinAddresses.toArray());

View File

@ -23,6 +23,7 @@ import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
import com.djrapitops.plan.storage.database.queries.QueryStatement; import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.sql.building.Select; import com.djrapitops.plan.storage.database.sql.building.Select;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import com.djrapitops.plan.utilities.java.Maps; import com.djrapitops.plan.utilities.java.Maps;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
@ -110,7 +111,7 @@ public class ServerQueries {
return fetchServerMatchingIdentifier(serverUUID.toString()); return fetchServerMatchingIdentifier(serverUUID.toString());
} }
public static Query<Optional<Server>> fetchServerMatchingIdentifier(String identifier) { public static Query<Optional<Server>> fetchServerMatchingIdentifier(@Untrusted String identifier) {
String sql = SELECT + '*' + FROM + ServerTable.TABLE_NAME + String sql = SELECT + '*' + FROM + ServerTable.TABLE_NAME +
WHERE + "(LOWER(" + ServerTable.SERVER_UUID + ") LIKE LOWER(?)" + WHERE + "(LOWER(" + ServerTable.SERVER_UUID + ") LIKE LOWER(?)" +
OR + "LOWER(" + ServerTable.NAME + ") LIKE LOWER(?)" + OR + "LOWER(" + ServerTable.NAME + ") LIKE LOWER(?)" +
@ -283,7 +284,7 @@ public class ServerQueries {
return db -> Maps.reverse(db.query(fetchServerNames())); return db -> Maps.reverse(db.query(fetchServerNames()));
} }
public static Query<List<ServerUUID>> fetchServersMatchingIdentifiers(List<String> serverNames) { public static Query<List<ServerUUID>> fetchServersMatchingIdentifiers(@Untrusted List<String> serverNames) {
return db -> { return db -> {
Map<String, ServerUUID> nameToUUIDMap = db.query(ServerQueries.fetchServerNamesToUUIDs()); Map<String, ServerUUID> nameToUUIDMap = db.query(ServerQueries.fetchServerNamesToUUIDs());
return serverNames.stream() return serverNames.stream()

View File

@ -23,7 +23,7 @@ import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.queries.QueryStatement; import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.utilities.Benchmark; import com.djrapitops.plan.utilities.dev.Benchmark;
import com.djrapitops.plan.utilities.java.Lists; import com.djrapitops.plan.utilities.java.Lists;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;

View File

@ -25,6 +25,7 @@ import com.djrapitops.plan.storage.database.sql.tables.NicknamesTable;
import com.djrapitops.plan.storage.database.sql.tables.ServerTable; import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable; import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -125,7 +126,7 @@ public class UserIdentifierQueries {
* @param playerName Name of the player, case does not matter. * @param playerName Name of the player, case does not matter.
* @return Optional: UUID if found, empty if not. * @return Optional: UUID if found, empty if not.
*/ */
public static Query<Optional<UUID>> fetchPlayerUUIDOf(String playerName) { public static Query<Optional<UUID>> fetchPlayerUUIDOf(@Untrusted String playerName) {
String sql = Select.from(UsersTable.TABLE_NAME, UsersTable.USER_UUID) String sql = Select.from(UsersTable.TABLE_NAME, UsersTable.USER_UUID)
.where("UPPER(" + UsersTable.USER_NAME + ")=UPPER(?)") .where("UPPER(" + UsersTable.USER_NAME + ")=UPPER(?)")
.toString(); .toString();
@ -172,7 +173,7 @@ public class UserIdentifierQueries {
}; };
} }
public static Query<List<String>> fetchMatchingPlayerNames(String searchFor) { public static Query<List<String>> fetchMatchingPlayerNames(@Untrusted String searchFor) {
String sql = SELECT + DISTINCT + UsersTable.USER_NAME + String sql = SELECT + DISTINCT + UsersTable.USER_NAME +
FROM + UsersTable.TABLE_NAME + FROM + UsersTable.TABLE_NAME +
WHERE + "LOWER(" + UsersTable.USER_NAME + ") LIKE LOWER(?)" + WHERE + "LOWER(" + UsersTable.USER_NAME + ") LIKE LOWER(?)" +

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.sql.tables.CookieTable; import com.djrapitops.plan.storage.database.sql.tables.CookieTable;
import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; import com.djrapitops.plan.storage.database.sql.tables.SecurityTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable; import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -43,7 +44,7 @@ public class WebUserQueries {
/* Static method class */ /* Static method class */
} }
public static Query<Optional<User>> fetchUser(String username) { public static Query<Optional<User>> fetchUser(@Untrusted String username) {
String sql = SELECT + '*' + FROM + SecurityTable.TABLE_NAME + String sql = SELECT + '*' + FROM + SecurityTable.TABLE_NAME +
LEFT_JOIN + UsersTable.TABLE_NAME + " on " + SecurityTable.LINKED_TO + "=" + UsersTable.USER_UUID + LEFT_JOIN + UsersTable.TABLE_NAME + " on " + SecurityTable.LINKED_TO + "=" + UsersTable.USER_UUID +
WHERE + SecurityTable.USERNAME + "=?" + LIMIT + "1"; WHERE + SecurityTable.USERNAME + "=?" + LIMIT + "1";

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.storage.database.transactions.events;
import com.djrapitops.plan.storage.database.sql.tables.CookieTable; import com.djrapitops.plan.storage.database.sql.tables.CookieTable;
import com.djrapitops.plan.storage.database.transactions.ExecStatement; import com.djrapitops.plan.storage.database.transactions.ExecStatement;
import com.djrapitops.plan.storage.database.transactions.Transaction; import com.djrapitops.plan.storage.database.transactions.Transaction;
import com.djrapitops.plan.utilities.dev.Untrusted;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
@ -26,10 +27,11 @@ import java.sql.SQLException;
public class CookieChangeTransaction extends Transaction { public class CookieChangeTransaction extends Transaction {
private final String username; private final String username;
@Untrusted
private final String cookie; // Null if removing private final String cookie; // Null if removing
private final Long expires; private final Long expires;
private CookieChangeTransaction(String username, String cookie, Long expires) { private CookieChangeTransaction(String username, @Untrusted String cookie, Long expires) {
this.username = username; this.username = username;
this.cookie = cookie; this.cookie = cookie;
this.expires = expires; this.expires = expires;
@ -43,7 +45,7 @@ public class CookieChangeTransaction extends Transaction {
return new CookieChangeTransaction(username, null, null); return new CookieChangeTransaction(username, null, null);
} }
public static CookieChangeTransaction removeCookie(String cookie) { public static CookieChangeTransaction removeCookie(@Untrusted String cookie) {
return new CookieChangeTransaction(null, cookie, null); return new CookieChangeTransaction(null, cookie, null);
} }

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable; import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable;
import com.djrapitops.plan.storage.database.transactions.ExecStatement; import com.djrapitops.plan.storage.database.transactions.ExecStatement;
import com.djrapitops.plan.storage.database.transactions.Transaction; import com.djrapitops.plan.storage.database.transactions.Transaction;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -33,10 +34,11 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
public class StoreJoinAddressTransaction extends Transaction { public class StoreJoinAddressTransaction extends Transaction {
@Untrusted
private final Supplier<String> joinAddress; private final Supplier<String> joinAddress;
private int newId; private int newId;
public StoreJoinAddressTransaction(String joinAddress) { public StoreJoinAddressTransaction(@Untrusted String joinAddress) {
this(() -> joinAddress); this(() -> joinAddress);
} }
@ -56,12 +58,13 @@ public class StoreJoinAddressTransaction extends Transaction {
return new HasMoreThanZeroQueryStatement(sql) { return new HasMoreThanZeroQueryStatement(sql) {
@Override @Override
public void prepare(PreparedStatement statement) throws SQLException { public void prepare(PreparedStatement statement) throws SQLException {
String address = getAddress(); @Untrusted String address = getAddress();
statement.setString(1, address); statement.setString(1, address);
} }
}; };
} }
@Untrusted
private String getAddress() { private String getAddress() {
return StringUtils.truncate(joinAddress.get(), JoinAddressTable.JOIN_ADDRESS_MAX_LENGTH); return StringUtils.truncate(joinAddress.get(), JoinAddressTable.JOIN_ADDRESS_MAX_LENGTH);
} }

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.SubSystem;
import com.djrapitops.plan.exceptions.EnableException; import com.djrapitops.plan.exceptions.EnableException;
import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.CustomizedFileSettings; import com.djrapitops.plan.settings.config.paths.CustomizedFileSettings;
import com.djrapitops.plan.utilities.dev.Untrusted;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
@ -90,7 +91,7 @@ public class PlanFiles implements SubSystem {
return getFileFromPluginFolder("locale.yml"); return getFileFromPluginFolder("locale.yml");
} }
public File getFileFromPluginFolder(String name) { public File getFileFromPluginFolder(@Untrusted String name) {
return new File(dataFolder, name.replace("/", File.separator)); return new File(dataFolder, name.replace("/", File.separator));
} }

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.utilities; package com.djrapitops.plan.utilities;
import com.djrapitops.plan.exceptions.PassEncryptException; import com.djrapitops.plan.exceptions.PassEncryptException;
import com.djrapitops.plan.utilities.dev.Untrusted;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
@ -62,7 +63,7 @@ public class PassEncryptUtil {
* @return Hash + salt * @return Hash + salt
* @throws CannotPerformOperationException If the hash creation fails * @throws CannotPerformOperationException If the hash creation fails
*/ */
public static String createHash(String password) { public static String createHash(@Untrusted String password) {
return createHash(password.toCharArray()); return createHash(password.toCharArray());
} }
@ -93,7 +94,7 @@ public class PassEncryptUtil {
* @throws CannotPerformOperationException If hashing fails * @throws CannotPerformOperationException If hashing fails
* @throws InvalidHashException If the hash is missing details. * @throws InvalidHashException If the hash is missing details.
*/ */
public static boolean verifyPassword(String password, String correctHash) { public static boolean verifyPassword(@Untrusted String password, String correctHash) {
return verifyPassword(password.toCharArray(), correctHash); return verifyPassword(password.toCharArray(), correctHash);
} }

View File

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>. * along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.djrapitops.plan.utilities; package com.djrapitops.plan.utilities.dev;
import com.djrapitops.plan.delivery.formatting.Formatter; import com.djrapitops.plan.delivery.formatting.Formatter;

View File

@ -0,0 +1,31 @@
/*
* 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.utilities.dev;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation for identifying untrusted data that has not been sanitized.
*
* @author AuroraLS3
*/
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD, ElementType.LOCAL_VARIABLE, ElementType.TYPE_PARAMETER, ElementType.TYPE_USE, ElementType.CONSTRUCTOR, ElementType.TYPE})
public @interface Untrusted {}