diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java
index 96e91b0e6..69a8e1035 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java
+++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java
@@ -100,6 +100,8 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
addItemsToCollection(request, responseWriter);
} else if (uri.equals("/banUser") && request.method() == HttpMethod.POST) {
banUser(request, responseWriter);
+ } else if (uri.equals("/resetUserPassword") && request.method() == HttpMethod.POST) {
+ resetUserPassword(request, responseWriter);
} else if (uri.equals("/banMultiple") && request.method() == HttpMethod.POST) {
banMultiple(request, responseWriter);
} else if (uri.equals("/banUserTemp") && request.method() == HttpMethod.POST) {
@@ -161,6 +163,25 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
return "OK";
}
+ private void resetUserPassword(HttpRequest request, ResponseWriter responseWriter) throws Exception {
+ validateAdmin(request);
+
+ HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request);
+ try {
+ String login = getFormParameterSafely(postDecoder, "login");
+
+ if (login==null)
+ throw new HttpProcessingException(400);
+
+ if (!_adminService.resetUserPassword(login))
+ throw new HttpProcessingException(404);
+
+ responseWriter.writeHtmlResponse("OK");
+ } finally {
+ postDecoder.destroy();
+ }
+ }
+
private void banUser(HttpRequest request, ResponseWriter responseWriter) throws Exception {
validateAdmin(request);
@@ -174,7 +195,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
if (!_adminService.banUser(login))
throw new HttpProcessingException(404);
- responseWriter.writeHtmlResponse("OK");
+ responseWriter.writeHtmlResponse("OK");
} finally {
postDecoder.destroy();
}
diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java
index d526906db..f675c78bc 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java
+++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java
@@ -3,6 +3,7 @@ package com.gempukku.lotro.async.handler;
import com.gempukku.lotro.async.HttpProcessingException;
import com.gempukku.lotro.async.ResponseWriter;
import com.gempukku.lotro.game.Player;
+import com.mysql.cj.util.StringUtils;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
@@ -30,7 +31,10 @@ public class LoginRequestHandler extends LotroServerRequestHandler implements Ur
Player player = _playerDao.loginUser(login, password);
if (player != null) {
- if (player.getType().contains("u")) {
+ if (StringUtils.isNullOrEmpty(player.getPassword())) {
+ throw new HttpProcessingException(202);
+ }
+ if (player.getType().contains(Player.Type.USER.getValue())) {
final Date bannedUntil = player.getBannedUntil();
if (bannedUntil != null && bannedUntil.after(new Date()))
throw new HttpProcessingException(409);
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/includes/admin/userAdmin.html b/gemp-lotr/gemp-lotr-async/src/main/web/includes/admin/userAdmin.html
index 67daeb6e2..5166ff73f 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/includes/admin/userAdmin.html
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/includes/admin/userAdmin.html
@@ -3,6 +3,15 @@
+
Reset User Password
+
+ Name (case-sensitive):
+ Ready.
+
+
+
Ban User
Permanently
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js
index 5134b27ce..6949f7cc6 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js
@@ -52,6 +52,16 @@ var GempLotrCommunication = Class.extend({
callback(xml);
};
},
+
+ deliveryCheckStatus:function (callback) {
+ var that = this;
+ return function (xml, status, request) {
+ var delivery = request.getResponseHeader("Delivery-Service-Package");
+ if (delivery == "true" && window.deliveryService != null)
+ that.getDelivery(window.deliveryService);
+ callback(xml, request.status);
+ };
+ },
getGameHistory:function (start, count, callback, errorMap) {
$.ajax({
@@ -817,6 +827,20 @@ var GempLotrCommunication = Class.extend({
});
},
+ resetUserPassword:function (login, callback, errorMap) {
+ $.ajax({
+ type:"POST",
+ url:this.url + "/admin/resetUserPassword",
+ cache:false,
+ data:{
+ login:login
+ },
+ success:this.deliveryCheck(callback),
+ error:this.errorCheck(errorMap),
+ dataType:"html"
+ });
+ },
+
permabanUser:function (login, callback, errorMap) {
$.ajax({
type:"POST",
@@ -1050,7 +1074,7 @@ var GempLotrCommunication = Class.extend({
login:login,
password:password,
participantId:getUrlParam("participantId")},
- success:this.deliveryCheck(callback),
+ success:this.deliveryCheckStatus(callback),
error:this.errorCheck(errorMap),
dataType:"html"
});
@@ -1064,7 +1088,7 @@ var GempLotrCommunication = Class.extend({
login:login,
password:password,
participantId:getUrlParam("participantId")},
- success:this.deliveryCheck(callback),
+ success:this.deliveryCheckStatus(callback),
error:this.errorCheck(errorMap),
dataType:"html"
});
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/manage.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/manage.js
index cf5a81100..ef2a7b4a1 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/manage.js
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/manage.js
@@ -1,6 +1,21 @@
$("banMain").ready(
function () {
+ $("#reset-button").button().click(
+ function () {
+ let execute = confirm("Are you sure you want to reset the password for '" + $("#reset-input").val() + "'? This action cannot be undone.");
+
+ if(!execute)
+ return;
+
+ let resultdiv = $("#reset-result");
+ resultdiv.html("Processing...");
+
+ hall.comm.resetUserPassword($("#reset-input").val(), function (string) {
+ resultdiv.html(string);
+ }, banErrorMap(resultdiv));
+ });
+
$("#permaban-button").button().click(
function () {
let resultdiv = $("#permaban-result");
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/src/Login/login.js b/gemp-lotr/gemp-lotr-async/src/main/web/src/Login/login.js
index a990903a9..58fad4380 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/src/Login/login.js
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/src/Login/login.js
@@ -10,14 +10,22 @@ function register() {
if (password != password2) {
$(".error").html("Password and Password repeated are different! Try again");
} else {
- comm.register(login, password, function () {
- location.href = "/gemp-lotr/hall.html";
+ comm.register(login, password, function (_, status) {
+ if(status == "202") {
+ $(".error").html("Your password has successfully been reset! Please refresh the page and log in.");
+ }
+ else {
+ location.href = "/gemp-lotr/hall.html";
+ }
},
{
"0": function () {
alert("Unable to connect to server, either server is down or there is a problem" +
" with your internet connection");
},
+ "202": function () {
+ $(".error").html("Your password has successfully been reset! Please refresh the page and log in.");
+ },
"400": function () {
$(".error").html("Login is invalid. Login must be between 2-10 characters long, and contain only
" +
" english letters, numbers or _ (underscore) and - (dash) characters.");
@@ -45,24 +53,38 @@ function registrationScreen() {
function login() {
var login = $("#login").val();
var password = $("#password").val();
- comm.login(login, password, function () {
- location.href = "/gemp-lotr/hall.html";
+ comm.login(login, password, function (_, status) {
+ if(status == "202") {
+ registrationScreen();
+ $("#registerButton").html("Update Password");
+ $(".error").html("Your password must be reset. Please enter a new password.");
+ $("#login").val(login);
+ }
+ else {
+ location.href = "/gemp-lotr/hall.html";
+ }
},
{
"0": function () {
alert("Unable to connect to server, either server is down or there is a problem" +
" with your internet connection");
},
+ "202": function () {
+ registrationScreen();
+ $("#registerButton").html("Update Password");
+ $(".error").html("Your password must be reset. Please enter a new password.");
+ $("#login").val(login);
+ },
"401": function () {
$(".error").html("Invalid username or password. Try again.");
loginScreen();
},
"403": function () {
- $(".error").html("You have been permanently banned. If you think it was a mistake you can try sending a private message to Merrick_H on
TLHH forums.");
+ $(".error").html("You have been permanently banned. If you think it was a mistake please appeal with dmaz or ketura on
TLHH forums.");
+ $(".error").html("You have been temporarily banned. You can try logging in at a later time. If you think it was a mistake please appeal with dmaz or ketura on
Forgot your password? Contact ketura on the PC Discord.");
}
$(document).ready(
diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java
index b10e8d936..b358cc56a 100644
--- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java
+++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/DBDefs.java
@@ -64,6 +64,19 @@ public class DBDefs {
public static class Player {
public int id;
public String name;
+ public String password;
+ public String type;
+ public Integer last_login_reward;
+ public Integer banned_until;
+ public String create_ip;
+ public String last_ip;
+
+ public Date GetBannedUntilDate()
+ {
+ if(banned_until == null)
+ return null;
+ return new Date(banned_until);
+ }
}
public static class FormatStats {
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java
index 1642c101e..7df803d0b 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java
@@ -1,8 +1,61 @@
package com.gempukku.lotro.game;
+import com.gempukku.lotro.common.DBDefs;
+
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
+import java.util.Objects;
public class Player {
+
+ public enum Type {
+ ADMIN("a"),
+ //wow this is such a better idea than a blank column
+ //DEACTIVATED("d"),
+ LEAGUE_ADMIN("l"),
+ PLAY_TESTER("p"),
+ //PLAY_TESTING_ADMIN("t"),
+ //COMMENTATOR("c"),
+ //COMMENTATOR_ADMIN("m"),
+ UNBANNED("n"),
+ USER("u");
+
+ private final String _value;
+
+ Type(String value) {
+ _value = value;
+ }
+
+ public String getValue() {
+ return _value;
+ }
+
+ public String toString() {
+ return getValue();
+ }
+
+ public static List
getTypes(String typeString) {
+ List types = new ArrayList<>();
+ for (Type type : values()) {
+ if (typeString.contains(type.getValue())) {
+ types.add(type);
+ }
+ }
+ return types;
+ }
+
+ public static String getTypeString(List types) {
+ StringBuilder sb = new StringBuilder();
+ for (Type type : values()) {
+ if (types.contains(type)) {
+ sb.append(type.getValue());
+ }
+ }
+ return sb.toString();
+ }
+ }
+
private final int _id;
private final String _name;
private final String _password;
@@ -12,6 +65,10 @@ public class Player {
private final String _createIp;
private final String _lastIp;
+ public Player(DBDefs.Player def) {
+ this(def.id, def.name, def.password, def.type, def.last_login_reward, def.GetBannedUntilDate(), def.create_ip, def.last_ip);
+ }
+
public Player(int id, String name, String password, String type, Integer lastLoginReward, Date bannedUntil, String createIp, String lastIp) {
_id = id;
_name = name;
@@ -66,7 +123,7 @@ public class Player {
Player player = (Player) o;
- if (_name != null ? !_name.equals(player._name) : player._name != null) return false;
+ if (!Objects.equals(_name, player._name)) return false;
return true;
}
@@ -76,15 +133,15 @@ public class Player {
return _name != null ? _name.hashCode() : 0;
}
- public PlayerDefinition GetUserInfo() {
- return new PlayerDefinition(_name, _type);
+ public PlayerInfo GetUserInfo() {
+ return new PlayerInfo(_name, _type);
}
- public class PlayerDefinition {
+ public class PlayerInfo {
public String name;
public String type;
- public PlayerDefinition(String name, String info) {
+ public PlayerInfo(String name, String info) {
this.name = name;
type = info;
}
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java
index d497aca06..f3d906f0e 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java
@@ -30,6 +30,14 @@ public class CachedPlayerDAO implements PlayerDAO, Cached {
return _playerById.size() + _playerByName.size();
}
+ @Override
+ public boolean resetUserPassword(String login) throws SQLException {
+ final boolean success = _delegate.resetUserPassword(login);
+ if (success)
+ clearCache();
+ return success;
+ }
+
@Override
public boolean banPlayerPermanently(String login) throws SQLException {
final boolean success = _delegate.banPlayerPermanently(login);
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java
index 5d83c6219..9765aa70d 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java
@@ -13,7 +13,19 @@ import java.util.*;
public class DbPlayerDAO implements PlayerDAO {
private final String validLoginChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
- private final String _selectPlayer = "select id, name, password, type, last_login_reward, banned_until, create_ip, last_ip from player";
+ private final String _selectPlayer = """
+ SELECT
+ id,
+ name,
+ password,
+ type,
+ last_login_reward,
+ banned_until,
+ create_ip,
+ last_ip
+ FROM player
+ """;
+
private final DbAccess _dbAccess;
@@ -95,6 +107,29 @@ public class DbPlayerDAO implements PlayerDAO {
}
}
+ @Override
+ public boolean resetUserPassword(String login) throws SQLException {
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.beginTransaction()) {
+ String sql = """
+ UPDATE player
+ SET password = ''
+ WHERE name = :login
+ """;
+ conn.createQuery(sql)
+ .addParameter("login", login)
+ .executeUpdate();
+
+ conn.commit();
+ return true;
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to reset password", ex);
+ }
+ }
+
@Override
public boolean banPlayerPermanently(String login) throws SQLException {
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
@@ -152,17 +187,29 @@ public class DbPlayerDAO implements PlayerDAO {
@Override
public Player loginUser(String login, String password) throws SQLException {
- try (Connection conn = _dbAccess.getDataSource().getConnection()) {
- try (PreparedStatement statement = conn.prepareStatement(_selectPlayer + " where name=? and password=?")) {
- statement.setString(1, login);
- statement.setString(2, encodePassword(password));
- try (ResultSet rs = statement.executeQuery()) {
- if (rs.next()) {
- return getPlayerFromResultSet(rs);
- } else
- return null;
- }
+
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.open()) {
+ String sql = _selectPlayer +
+ """
+ WHERE name = :login
+ AND (password = :password OR password = '')
+ """;
+ List result = conn.createQuery(sql)
+ .addParameter("login", login)
+ .addParameter("password", encodePassword(password))
+ .executeAndFetch(DBDefs.Player.class);
+
+ var def = result.stream().findFirst().orElse(null);
+ if(def == null)
+ return null;
+
+ return new Player(def);
}
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to retrieve login entries", ex);
}
}
@@ -217,23 +264,61 @@ public class DbPlayerDAO implements PlayerDAO {
@Override
public synchronized boolean registerUser(String login, String password, String remoteAddr) throws SQLException, LoginInvalidException {
- boolean result = validateLogin(login);
- if (!result)
+ if (!validLoginName(login))
return false;
- try (Connection conn = _dbAccess.getDataSource().getConnection()) {
- try (PreparedStatement statement = conn.prepareStatement("insert into player (name, password, type, create_ip) values (?, ?, ?, ?)")) {
- statement.setString(1, login);
- statement.setString(2, encodePassword(password));
- statement.setString(3, "u");
- statement.setString(4, remoteAddr);
- statement.execute();
+ if(loginExists(login)) {
+ if(!needsPasswordReset(login))
+ return false;
+
+ //Login exists but has a blank/null password, meaning this user is actually performing a password reset
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.beginTransaction()) {
+ String sql = """
+ UPDATE player
+ SET password = :password
+ WHERE name = :login
+ """;
+ conn.createQuery(sql)
+ .addParameter("login", login)
+ .addParameter("password", encodePassword(password))
+ .executeUpdate();
+
+ conn.commit();
+ return true;
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to update password", ex);
+ }
+ }
+
+
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.beginTransaction()) {
+ String sql = """
+ INSERT INTO player (name, password, type, create_ip)
+ VALUES (:login, :password, :type, :create_ip)
+ """;
+ conn.createQuery(sql)
+ .addParameter("login", login)
+ .addParameter("password", encodePassword(password))
+ .addParameter("type", Player.Type.USER.toString())
+ .addParameter("create_ip", remoteAddr)
+ .executeUpdate();
+
+ conn.commit();
return true;
}
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to insert new user", ex);
}
}
- private boolean validateLogin(String login) throws SQLException, LoginInvalidException {
+ private boolean validLoginName(String login) throws LoginInvalidException {
if (login.length() < 2 || login.length() > 30)
throw new LoginInvalidException();
for (int i = 0; i < login.length(); i++) {
@@ -246,16 +331,50 @@ public class DbPlayerDAO implements PlayerDAO {
if (lowerCase.startsWith("admin") || lowerCase.startsWith("guest") || lowerCase.startsWith("system") || lowerCase.startsWith("bye"))
return false;
- try (Connection conn = _dbAccess.getDataSource().getConnection()) {
- try (PreparedStatement statement = conn.prepareStatement("select id, name from player where LOWER(name)=?")) {
- statement.setString(1, lowerCase);
- try (ResultSet rs = statement.executeQuery()) {
- if (rs.next()) {
- return false;
- } else
- return true;
- }
+ return true;
+ }
+
+ private boolean loginExists(String login) throws SQLException {
+
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.open()) {
+ String sql = _selectPlayer +
+ """
+ WHERE LOWER(name) = :login
+ """;
+ List result = conn.createQuery(sql)
+ .addParameter("login", login.toLowerCase())
+ .executeAndFetch(DBDefs.Player.class);
+
+ var def = result.stream().findFirst().orElse(null);
+ return def != null;
}
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to retrieve password reset entries", ex);
+ }
+ }
+
+ private boolean needsPasswordReset(String login) throws SQLException {
+ try {
+ Sql2o db = new Sql2o(_dbAccess.getDataSource());
+
+ try (org.sql2o.Connection conn = db.open()) {
+ String sql = _selectPlayer +
+ """
+ WHERE LOWER(name) = :login
+ AND (password = '' OR password IS NULL)
+ """;
+ List result = conn.createQuery(sql)
+ .addParameter("login", login.toLowerCase())
+ .executeAndFetch(DBDefs.Player.class);
+
+ var def = result.stream().findFirst().orElse(null);
+ return def != null;
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException("Unable to retrieve password reset entries", ex);
}
}
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java
index 1dfba9b15..a78847551 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java
@@ -12,6 +12,8 @@ public interface PlayerDAO {
public Player getPlayer(String playerName);
+ public boolean resetUserPassword(String login) throws SQLException;
+
public boolean banPlayerPermanently(String login) throws SQLException;
public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException;
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/service/AdminService.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/service/AdminService.java
index 2567970aa..c05d9a19c 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/service/AdminService.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/service/AdminService.java
@@ -18,6 +18,18 @@ public class AdminService {
_loggedUserHolder = loggedUserHolder;
}
+ public boolean resetUserPassword(String login) {
+ try {
+ final boolean success = _playerDAO.resetUserPassword(login);
+ if (!success)
+ return false;
+ _loggedUserHolder.forceLogoutUser(login);
+ return true;
+ } catch (SQLException exp) {
+ return false;
+ }
+ }
+
public boolean banUser(String login) {
try {
final boolean success = _playerDAO.banPlayerPermanently(login);