Added a fail message to web traffic if database is not open

This commit is contained in:
Rsl1122 2019-02-22 10:35:06 +02:00
parent ac7093237e
commit 871fa9b979
10 changed files with 51 additions and 25 deletions

View File

@ -17,6 +17,7 @@
package com.djrapitops.plan.command.commands;
import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.locale.Locale;
@ -70,12 +71,15 @@ public class InfoCommand extends CommandNode {
String updateAvailable = versionCheckSystem.isNewVersionAvailable() ? yes : no;
String connectedToBungee = connectionSystem.isServerAvailable() ? yes : no;
Database database = dbSystem.getDatabase();
String[] messages = {
locale.getString(CommandLang.HEADER_INFO),
"",
locale.getString(CommandLang.INFO_VERSION, plugin.getVersion()),
locale.getString(CommandLang.INFO_UPDATE, updateAvailable),
locale.getString(CommandLang.INFO_DATABASE, dbSystem.getDatabase().getType().getName()),
locale.getString(CommandLang.INFO_DATABASE, database.getType().getName() + " (" + database.getState().name() + ")"),
locale.getString(CommandLang.INFO_BUNGEE_CONNECTION, connectedToBungee),
"",
">"

View File

@ -71,7 +71,7 @@ public interface Database {
enum State {
CLOSED,
INITIALIZING,
PATCHING,
OPEN
}
}

View File

@ -89,7 +89,7 @@ public abstract class SQLDB extends AbstractDatabase {
List<Runnable> unfinishedTransactions = closeTransactionExecutor(transactionExecutor);
this.transactionExecutor = transactionExecutorServiceProvider.get();
setState(State.INITIALIZING);
setState(State.PATCHING);
setupDataSource();
setupDatabase();
@ -159,7 +159,7 @@ public abstract class SQLDB extends AbstractDatabase {
executeTransaction(new OperationCriticalTransaction() {
@Override
protected void performOperations() {
if (getState() == State.INITIALIZING) setState(State.OPEN);
if (getState() == State.PATCHING) setState(State.OPEN);
}
});
registerIndexCreationTask();

View File

@ -16,7 +16,6 @@
*/
package com.djrapitops.plan.system.webserver;
import com.djrapitops.plan.system.DebugChannels;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.locale.Locale;
import com.djrapitops.plan.system.settings.config.PlanConfig;
@ -26,7 +25,6 @@ import com.djrapitops.plan.system.webserver.auth.Authentication;
import com.djrapitops.plan.system.webserver.auth.BasicAuthentication;
import com.djrapitops.plan.system.webserver.response.PromptAuthorizationResponse;
import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plugin.benchmarking.Benchmark;
import com.djrapitops.plugin.benchmarking.Timings;
import com.djrapitops.plugin.logging.L;
import com.djrapitops.plugin.logging.console.PluginLogger;
@ -85,14 +83,8 @@ public class RequestHandler implements HttpHandler {
Request request = new Request(exchange, locale);
request.setAuth(getAuthorization(requestHeaders));
String requestString = request.toString();
timings.start(requestString);
int responseCode = -1;
boolean inDevMode = config.isTrue(PluginSettings.DEV_MODE);
try {
Response response = responseHandler.getResponse(request);
responseCode = response.getCode();
if (response instanceof PromptAuthorizationResponse) {
responseHeaders.set("WWW-Authenticate", "Basic realm=\"/\"");
}
@ -100,18 +92,12 @@ public class RequestHandler implements HttpHandler {
response.setResponseHeaders(responseHeaders);
response.send(exchange, locale, theme);
} catch (Exception e) {
if (inDevMode) {
if (config.isTrue(PluginSettings.DEV_MODE)) {
logger.warn("THIS ERROR IS ONLY LOGGED IN DEV MODE:");
errorHandler.log(L.WARN, this.getClass(), e);
}
} finally {
exchange.close();
if (inDevMode) {
logger.getDebugLogger().logOn(
DebugChannels.WEB_REQUESTS,
timings.end(requestString).map(Benchmark::toString).orElse("-") + " Code: " + responseCode
);
}
}
}

View File

@ -55,6 +55,11 @@ public class BasicAuthentication implements Authentication {
String user = userInfo[0];
String passwordRaw = userInfo[1];
Database.State dbState = database.getState();
if (dbState != Database.State.OPEN) {
throw new WebUserAuthException(FailReason.DATABASE_NOT_OPEN, "State was: " + dbState.name());
}
try {
WebUser webUser = database.query(WebUserQueries.fetchWebUser(user))
.orElseThrow(() -> new WebUserAuthException(FailReason.USER_DOES_NOT_EXIST, user));

View File

@ -28,6 +28,7 @@ public enum FailReason implements Lang {
USER_AND_PASS_NOT_SPECIFIED("User and Password not specified"),
USER_DOES_NOT_EXIST("User does not exist"),
USER_PASS_MISMATCH("User and Password did not match"),
DATABASE_NOT_OPEN("Database is not open, check db status with /plan info"),
ERROR("Authentication failed due to error");
private final String reason;

View File

@ -17,9 +17,11 @@
package com.djrapitops.plan.system.webserver.pages;
import com.djrapitops.plan.api.exceptions.WebUserAuthException;
import com.djrapitops.plan.api.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.data.WebUser;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.PlayerFetchQueries;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.InfoSystem;
@ -78,6 +80,10 @@ public class PlayerPageHandler implements PageHandler {
return responseFactory.uuidNotFound404();
}
try {
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
throw new ForbiddenException("Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info");
}
// TODO Move this Database dependency to PlayerPage generation in PageFactory instead.
if (dbSystem.getDatabase().query(PlayerFetchQueries.isPlayerRegistered(uuid))) {
if (raw) {

View File

@ -17,6 +17,10 @@
package com.djrapitops.plan.system.webserver.pages;
import com.djrapitops.plan.api.exceptions.WebUserAuthException;
import com.djrapitops.plan.api.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.webserver.Request;
import com.djrapitops.plan.system.webserver.auth.Authentication;
import com.djrapitops.plan.system.webserver.cache.PageId;
@ -36,15 +40,24 @@ import java.util.List;
@Singleton
public class PlayersPageHandler implements PageHandler {
private final DBSystem dbSystem;
private final ResponseFactory responseFactory;
@Inject
public PlayersPageHandler(ResponseFactory responseFactory) {
public PlayersPageHandler(
DBSystem dbSystem,
ResponseFactory responseFactory
) {
this.dbSystem = dbSystem;
this.responseFactory = responseFactory;
}
@Override
public Response getResponse(Request request, List<String> target) {
public Response getResponse(Request request, List<String> target) throws WebException {
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
throw new ForbiddenException("Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info");
}
return ResponseCache.loadResponse(PageId.PLAYERS.id(), responseFactory::playersPageResponse);
}

View File

@ -18,8 +18,10 @@ package com.djrapitops.plan.system.webserver.pages;
import com.djrapitops.plan.api.exceptions.WebUserAuthException;
import com.djrapitops.plan.api.exceptions.connection.ConnectionFailException;
import com.djrapitops.plan.api.exceptions.connection.ForbiddenException;
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
import com.djrapitops.plan.api.exceptions.connection.WebException;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.info.InfoSystem;
@ -70,11 +72,12 @@ public class ServerPageHandler implements PageHandler {
}
@Override
public Response getResponse(Request request, List<String> target) {
public Response getResponse(Request request, List<String> target) throws WebException {
UUID serverUUID = getServerUUID(target);
boolean raw = target.size() >= 2 && target.get(1).equalsIgnoreCase("raw");
if (raw) {
checkDBState();
return ResponseCache.loadResponse(PageId.RAW_SERVER.of(serverUUID), () -> responseFactory.rawServerPageResponse(serverUUID));
}
@ -83,6 +86,7 @@ public class ServerPageHandler implements PageHandler {
if (response != null) {
return response;
} else {
checkDBState();
if ((Check.isBungeeAvailable() || Check.isVelocityAvailable()) && serverInfo.getServerUUID().equals(serverUUID)) {
return ResponseCache.loadResponse(PageId.SERVER.of(serverUUID), responseFactory::networkPageResponse);
}
@ -90,6 +94,13 @@ public class ServerPageHandler implements PageHandler {
}
}
private void checkDBState() throws ForbiddenException {
Database.State dbState = dbSystem.getDatabase().getState();
if (dbState != Database.State.OPEN) {
throw new ForbiddenException("Database is " + dbState.name() + " - Please try again later. You can check database status with /plan info");
}
}
// TODO Split responsibility so that this method does not call system to refresh and also render a refresh page.
private Response refreshNow(UUID serverUUID) {
processing.submitNonCritical(() -> {

View File

@ -45,7 +45,7 @@ public class PromptAuthorizationResponse extends ErrorResponse {
public static PromptAuthorizationResponse getBasicAuthResponse(VersionCheckSystem versionCheckSystem, PlanFiles files) throws IOException {
PromptAuthorizationResponse response = new PromptAuthorizationResponse(versionCheckSystem, files);
response.setHeader("HTTP/1.1 401 Access Denied\r\n"
+ "WWW-Authenticate: Basic realm=\"/\";");
+ "WWW-Authenticate: Basic realm=\"Plan WebUser (/plan register)\";");
response.setParagraph("Authentication Failed." + TIPS);
response.replacePlaceholders();
@ -54,8 +54,6 @@ public class PromptAuthorizationResponse extends ErrorResponse {
public static PromptAuthorizationResponse getBasicAuthResponse(WebUserAuthException e, VersionCheckSystem versionCheckSystem, PlanFiles files) throws IOException {
PromptAuthorizationResponse response = new PromptAuthorizationResponse(versionCheckSystem, files);
response.setHeader("HTTP/1.1 401 Access Denied\r\n"
+ "WWW-Authenticate: Basic realm=\"/\";");
FailReason failReason = e.getFailReason();
String reason = failReason.getReason();
@ -70,6 +68,8 @@ public class PromptAuthorizationResponse extends ErrorResponse {
reason += errorBuilder.toString();
}
response.setHeader("HTTP/1.1 401 Access Denied\r\n"
+ "WWW-Authenticate: Basic realm=\"" + failReason.getReason() + "\";");
response.setParagraph("Authentication Failed.</p><p><b>Reason: " + reason + "</b></p><p>" + TIPS);
response.replacePlaceholders();
return response;