Stop ActiveCookieStore from logging database exception on plugin disable

Affects issues:
- Fixed #2188
This commit is contained in:
Aurora Lahtela 2022-05-07 09:26:54 +03:00
parent 64146cc6eb
commit 55ceeb3ad2
5 changed files with 54 additions and 20 deletions

View File

@ -18,12 +18,14 @@ package com.djrapitops.plan.delivery.webserver.auth;
import com.djrapitops.plan.SubSystem;
import com.djrapitops.plan.delivery.domain.auth.User;
import com.djrapitops.plan.exceptions.database.DBOpException;
import com.djrapitops.plan.processing.Processing;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries;
import com.djrapitops.plan.storage.database.transactions.events.CookieChangeTransaction;
import net.playeranalytics.plugin.server.PluginLogger;
import org.apache.commons.codec.digest.DigestUtils;
import javax.inject.Inject;
@ -38,24 +40,26 @@ import java.util.concurrent.TimeUnit;
public class ActiveCookieStore implements SubSystem {
private static final Map<String, User> USERS_BY_COOKIE = new ConcurrentHashMap<>();
public static long cookieExpiresAfter = TimeUnit.HOURS.toMillis(2L);
private static ActiveCookieStore activeCookieStore;
public static long cookieExpiresAfterMs = TimeUnit.HOURS.toMillis(2L);
private final ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask;
private final PlanConfig config;
private final DBSystem dbSystem;
private final Processing processing;
private final PluginLogger logger;
@Inject
public ActiveCookieStore(
ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask,
PlanConfig config,
DBSystem dbSystem,
Processing processing
Processing processing,
PluginLogger logger
) {
this.logger = logger;
Holder.setActiveCookieStore(this);
this.activeCookieExpiryCleanupTask = activeCookieExpiryCleanupTask;
ActiveCookieStore.activeCookieStore = this;
this.config = config;
this.dbSystem = dbSystem;
@ -63,7 +67,7 @@ public class ActiveCookieStore implements SubSystem {
}
private static void removeCookieStatic(String cookie) {
activeCookieStore.removeCookie(cookie);
Holder.getActiveCookieStore().removeCookie(cookie);
}
public static void removeUserCookie(String username) {
@ -73,18 +77,27 @@ public class ActiveCookieStore implements SubSystem {
.ifPresent(ActiveCookieStore::removeCookieStatic);
}
private static void setCookiesExpireAfter(Long expireAfterMs) {
cookieExpiresAfterMs = expireAfterMs;
}
@Override
public void enable() {
cookieExpiresAfter = config.get(WebserverSettings.COOKIES_EXPIRE_AFTER);
ActiveCookieStore.setCookiesExpireAfter(config.get(WebserverSettings.COOKIES_EXPIRE_AFTER));
processing.submitNonCritical(this::loadActiveCookies);
}
private void loadActiveCookies() {
USERS_BY_COOKIE.clear();
USERS_BY_COOKIE.putAll(dbSystem.getDatabase().query(WebUserQueries.fetchActiveCookies()));
for (Map.Entry<String, Long> entry : dbSystem.getDatabase().query(WebUserQueries.getCookieExpiryTimes()).entrySet()) {
long timeToExpiry = Math.max(entry.getValue() - System.currentTimeMillis(), 0L);
activeCookieExpiryCleanupTask.addExpiry(entry.getKey(), System.currentTimeMillis() + timeToExpiry);
try {
USERS_BY_COOKIE.putAll(dbSystem.getDatabase().query(WebUserQueries.fetchActiveCookies()));
for (Map.Entry<String, Long> entry : dbSystem.getDatabase().query(WebUserQueries.getCookieExpiryTimes()).entrySet()) {
long timeToExpiry = Math.max(entry.getValue() - System.currentTimeMillis(), 0L);
activeCookieExpiryCleanupTask.addExpiry(entry.getKey(), System.currentTimeMillis() + timeToExpiry);
}
} catch (DBOpException databaseClosedUnexpectedly) {
logger.info("Database closed unexpectedly so active cookies could not be loaded.");
// Safe to ignore https://github.com/plan-player-analytics/Plan/issues/2188
}
}
@ -101,13 +114,13 @@ public class ActiveCookieStore implements SubSystem {
String cookie = DigestUtils.sha256Hex(user.getUsername() + UUID.randomUUID() + System.currentTimeMillis());
USERS_BY_COOKIE.put(cookie, user);
saveNewCookie(user, cookie, System.currentTimeMillis());
activeCookieExpiryCleanupTask.addExpiry(cookie, System.currentTimeMillis() + cookieExpiresAfter);
activeCookieExpiryCleanupTask.addExpiry(cookie, System.currentTimeMillis() + cookieExpiresAfterMs);
return cookie;
}
private void saveNewCookie(User user, String cookie, long now) {
dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.storeCookie(
user.getUsername(), cookie, now + cookieExpiresAfter
user.getUsername(), cookie, now + cookieExpiresAfterMs
));
}
@ -127,4 +140,18 @@ public class ActiveCookieStore implements SubSystem {
disable();
dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.removeAll());
}
public static class Holder {
private static ActiveCookieStore activeCookieStore;
private Holder() {}
public static ActiveCookieStore getActiveCookieStore() {
return activeCookieStore;
}
public static void setActiveCookieStore(ActiveCookieStore activeCookieStore) {
Holder.activeCookieStore = activeCookieStore;
}
}
}

View File

@ -64,7 +64,7 @@ public class LoginResolver implements NoAuthResolver {
public Response getResponse(String cookie) {
return Response.builder()
.setStatus(200)
.setHeader("Set-Cookie", "auth=" + cookie + "; Path=/; Max-Age=" + ActiveCookieStore.cookieExpiresAfter + "; SameSite=Lax; Secure;")
.setHeader("Set-Cookie", "auth=" + cookie + "; Path=/; Max-Age=" + ActiveCookieStore.cookieExpiresAfterMs + "; SameSite=Lax; Secure;")
.setJSONContent(Collections.singletonMap("success", true))
.build();
}

View File

@ -80,9 +80,9 @@ public abstract class Transaction {
try {
initializeConnection(db);
if (shouldBeExecuted()) {
initializeTransaction(db);
initializeTransaction();
if (this instanceof Patch) {
db.getLogger().info(db.getLocale().getString(PluginLang.DB_APPLY_PATCH, getClass().getSimpleName()));
db.getLogger().info(db.getLocale().getString(PluginLang.DB_APPLY_PATCH, getName()));
}
performOperations();
if (connection != null) connection.commit();
@ -171,7 +171,7 @@ public abstract class Transaction {
}
}
private void initializeTransaction(SQLDB db) {
private void initializeTransaction() {
try {
createSavePoint();
} catch (SQLException e) {
@ -269,4 +269,9 @@ public abstract class Transaction {
public boolean dbIsNotUnderHeavyLoad() {
return !db.isUnderHeavyLoad();
}
public String getName() {
String simpleName = getClass().getSimpleName();
return simpleName.isEmpty() ? getClass().getName() : simpleName;
}
}

View File

@ -28,6 +28,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import utilities.TestConstants;
import utilities.TestPluginLogger;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@ -48,8 +49,8 @@ class ActiveCookieStoreTest {
Mockito.mock(ActiveCookieExpiryCleanupTask.class),
Mockito.mock(PlanConfig.class),
dbSystem,
Mockito.mock(Processing.class)
);
Mockito.mock(Processing.class),
new TestPluginLogger());
user = new User(TestConstants.PLAYER_ONE_NAME, "console", null, PassEncryptUtil.createHash("testPass"), 0, WebUser.getPermissionsForLevel(0));
}

View File

@ -31,6 +31,7 @@ import com.djrapitops.plan.utilities.PassEncryptUtil;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import utilities.TestConstants;
import utilities.TestPluginLogger;
import java.util.Collections;
import java.util.Map;
@ -122,8 +123,8 @@ public interface WebUserQueriesTest extends DatabaseTestPreparer {
Mockito.mock(ActiveCookieExpiryCleanupTask.class),
Mockito.mock(PlanConfig.class),
dbSystem(),
Mockito.mock(Processing.class)
);
Mockito.mock(Processing.class),
new TestPluginLogger());
}
@Test