mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +08:00
Added a logout command
Permission: plan.logout.other Usage: /plan logout * or /plan logout <username> Used for forcing a logout for users.
This commit is contained in:
parent
fb4b272844
commit
07cca1f008
@ -105,6 +105,7 @@ public class PlanCommand {
|
||||
|
||||
.subcommand(registerCommand())
|
||||
.subcommand(unregisterCommand())
|
||||
.subcommand(logoutCommand())
|
||||
.subcommand(webUsersCommand())
|
||||
|
||||
.subcommand(acceptCommand())
|
||||
@ -239,6 +240,17 @@ public class PlanCommand {
|
||||
.build();
|
||||
}
|
||||
|
||||
private Subcommand logoutCommand() {
|
||||
return Subcommand.builder()
|
||||
.requirePermission(Permissions.LOGOUT_OTHER)
|
||||
.requiredArgument(locale.getString(HelpLang.ARG_USERNAME), locale.getString(HelpLang.DESC_ARG_USERNAME))
|
||||
.description(locale.getString(HelpLang.LOGOUT))
|
||||
.inDepthDescription(locale.getString(DeepHelpLang.LOGOUT))
|
||||
.onCommand(registrationCommands::onLogoutCommand)
|
||||
.onTabComplete(this::webUserNames)
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<String> webUserNames(CMDSender sender, Arguments arguments) {
|
||||
if (!sender.hasPermission(Permissions.UNREGISTER_OTHER)) {
|
||||
return Collections.emptyList();
|
||||
|
@ -234,4 +234,20 @@ public class RegistrationCommands {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void onLogoutCommand(CMDSender sender, Arguments arguments) {
|
||||
Optional<String> username = arguments.get(0);
|
||||
if (!username.isPresent()) {
|
||||
throw new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ONE_ARG, locale.getString(HelpLang.ARG_USERNAME) + "/*"));
|
||||
}
|
||||
|
||||
String loggingOut = username.get();
|
||||
|
||||
if ("*".equals(loggingOut)) {
|
||||
activeCookieStore.removeAll();
|
||||
} else {
|
||||
ActiveCookieStore.removeUserCookie(loggingOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,14 +25,13 @@ 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.scheduling.RunnableFactory;
|
||||
import net.playeranalytics.plugin.scheduling.Task;
|
||||
import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -47,6 +46,8 @@ public class ActiveCookieStore implements SubSystem {
|
||||
private final RunnableFactory runnableFactory;
|
||||
private final Processing processing;
|
||||
|
||||
private final Collection<Task> expiryTasks;
|
||||
|
||||
@Inject
|
||||
public ActiveCookieStore(
|
||||
PlanConfig config,
|
||||
@ -60,6 +61,8 @@ public class ActiveCookieStore implements SubSystem {
|
||||
this.dbSystem = dbSystem;
|
||||
this.processing = processing;
|
||||
this.runnableFactory = runnableFactory;
|
||||
|
||||
expiryTasks = new ArrayList<>();
|
||||
}
|
||||
|
||||
private static void removeCookieStatic(String cookie) {
|
||||
@ -84,14 +87,22 @@ public class ActiveCookieStore implements SubSystem {
|
||||
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);
|
||||
runnableFactory.create(() -> removeCookie(entry.getKey()))
|
||||
.runTaskLaterAsynchronously(TimeAmount.toTicks(timeToExpiry, TimeUnit.MILLISECONDS));
|
||||
expiryTasks.add(runnableFactory.create(() -> removeCookie(entry.getKey()))
|
||||
.runTaskLaterAsynchronously(TimeAmount.toTicks(timeToExpiry, TimeUnit.MILLISECONDS)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
USERS_BY_COOKIE.clear();
|
||||
expiryTasks.forEach(task -> {
|
||||
try {
|
||||
task.cancel();
|
||||
} catch (Exception e) {
|
||||
// Ignore, task has already been cancelled
|
||||
}
|
||||
});
|
||||
expiryTasks.clear();
|
||||
}
|
||||
|
||||
public Optional<User> checkCookie(String cookie) {
|
||||
@ -102,6 +113,8 @@ 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());
|
||||
expiryTasks.add(runnableFactory.create(() -> removeCookie(cookie))
|
||||
.runTaskLaterAsynchronously(TimeAmount.toTicks(cookieExpiresAfter, TimeUnit.MILLISECONDS)));
|
||||
return cookie;
|
||||
}
|
||||
|
||||
@ -122,4 +135,9 @@ public class ActiveCookieStore implements SubSystem {
|
||||
private void deleteCookie(String username) {
|
||||
dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.removeCookie(username));
|
||||
}
|
||||
|
||||
public void removeAll() {
|
||||
disable();
|
||||
dbSystem.getDatabase().executeTransaction(CookieChangeTransaction.removeAll());
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ public enum Permissions {
|
||||
REGISTER_OTHER("plan.register.other"),
|
||||
UNREGISTER_SELF("plan.unregister.self"),
|
||||
UNREGISTER_OTHER("plan.unregister.other"),
|
||||
LOGOUT_OTHER("plan.logout.other"),
|
||||
INFO("plan.info"),
|
||||
RELOAD("plan.reload"),
|
||||
DISABLE("plan.disable"),
|
||||
|
@ -31,6 +31,7 @@ public enum DeepHelpLang implements Lang {
|
||||
INGAME("In Depth Help - /plan ingame", "Displays some information about the player in game."),
|
||||
REGISTER("In Depth Help - /plan register", "Use without arguments to get link to register page. Use --code [code] after registration to get a user."),
|
||||
UNREGISTER("In Depth Help - /plan unregister", "Use without arguments to unregister player linked user, or with username argument to unregister another user."),
|
||||
LOGOUT("In Depth Help - /plan logout", "Give username argument to log out another user from the panel, give * as argument to log out everyone."),
|
||||
INFO("In Depth Help - /plan info", "Display the current status of the plugin."),
|
||||
RELOAD("In Depth Help - /plan reload", "Disable and enable the plugin to reload any changes in config."),
|
||||
DISABLE("In Depth Help - /plan disable", "Disable the plugin or part of it until next reload/restart."),
|
||||
|
@ -69,7 +69,8 @@ public enum HelpLang implements Lang {
|
||||
DB_UNINSTALLED("Command Help - /plan db uninstalled", "Set a server as uninstalled in the database."),
|
||||
EXPORT("Command Help - /plan export", "Export html or json files manually"),
|
||||
IMPORT("Command Help - /plan import", "Import data"),
|
||||
JSON("Command Help - /plan json", "View json of Player's raw data.");
|
||||
JSON("Command Help - /plan json", "View json of Player's raw data."),
|
||||
LOGOUT("Command Help - /plan logout", "Log out other users from the panel.");
|
||||
|
||||
private final String identifier;
|
||||
private final String defaultValue;
|
||||
|
@ -46,6 +46,8 @@ public class CookieTable {
|
||||
public static final String DELETE_OLDER_STATEMENT = "DELETE FROM " + TABLE_NAME +
|
||||
WHERE + EXPIRES + "<=?";
|
||||
|
||||
public static final String DELETE_ALL_STATEMENT = "DELETE FROM " + TABLE_NAME;
|
||||
|
||||
|
||||
private CookieTable() {
|
||||
/* Static information class */
|
||||
|
@ -45,6 +45,7 @@ public class RemoveEverythingTransaction extends ThrowawayTransaction {
|
||||
clearTable(TPSTable.TABLE_NAME);
|
||||
clearTable(SecurityTable.TABLE_NAME);
|
||||
clearTable(ServerTable.TABLE_NAME);
|
||||
clearTable(CookieTable.TABLE_NAME);
|
||||
clearTable(ExtensionPlayerValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionServerValueTable.TABLE_NAME);
|
||||
clearTable(ExtensionGroupsTable.TABLE_NAME);
|
||||
|
@ -43,9 +43,20 @@ public class CookieChangeTransaction extends Transaction {
|
||||
return new CookieChangeTransaction(username, null, null);
|
||||
}
|
||||
|
||||
public static CookieChangeTransaction removeAll() {
|
||||
return new CookieChangeTransaction(null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
if (cookie == null) {
|
||||
if (username == null) {
|
||||
execute(new ExecStatement(CookieTable.DELETE_ALL_STATEMENT) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
// No parameters
|
||||
}
|
||||
});
|
||||
} else if (cookie == null) {
|
||||
execute(new ExecStatement(CookieTable.DELETE_BY_USER_STATEMENT) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
|
@ -60,6 +60,8 @@ permissions:
|
||||
default: true
|
||||
plan.unregister.other:
|
||||
default: op
|
||||
plan.logout.other:
|
||||
default: op
|
||||
plan.info:
|
||||
default: op
|
||||
plan.reload:
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.delivery.webserver.auth;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.WebUser;
|
||||
|
@ -98,9 +98,7 @@ public interface WebUserQueriesTest extends DatabaseTestPreparer {
|
||||
|
||||
cookieStore.removeCookie(cookie);
|
||||
|
||||
Map<String, User> result = db().query(WebUserQueries.fetchActiveCookies());
|
||||
Map<String, User> expected = Collections.emptyMap();
|
||||
assertEquals(expected, result);
|
||||
assertTrue(db().query(WebUserQueries.fetchActiveCookies()).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -116,8 +114,13 @@ public interface WebUserQueriesTest extends DatabaseTestPreparer {
|
||||
|
||||
assertFalse(cookieStore.checkCookie(cookie).isPresent());
|
||||
|
||||
Map<String, User> result = db().query(WebUserQueries.fetchActiveCookies());
|
||||
Map<String, User> expected = Collections.emptyMap();
|
||||
assertEquals(expected, result);
|
||||
assertTrue(db().query(WebUserQueries.fetchActiveCookies()).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
default void removeEverythingRemovesCookies() {
|
||||
activeCookieStoreSavesCookies();
|
||||
db().executeTransaction(new RemoveEverythingTransaction());
|
||||
assertTrue(db().query(WebUserQueries.fetchActiveCookies()).isEmpty());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user