Adding ability for admins to reset the passwords for users.
This commit is contained in:
@@ -100,6 +100,8 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
|
|||||||
addItemsToCollection(request, responseWriter);
|
addItemsToCollection(request, responseWriter);
|
||||||
} else if (uri.equals("/banUser") && request.method() == HttpMethod.POST) {
|
} else if (uri.equals("/banUser") && request.method() == HttpMethod.POST) {
|
||||||
banUser(request, responseWriter);
|
banUser(request, responseWriter);
|
||||||
|
} else if (uri.equals("/resetUserPassword") && request.method() == HttpMethod.POST) {
|
||||||
|
resetUserPassword(request, responseWriter);
|
||||||
} else if (uri.equals("/banMultiple") && request.method() == HttpMethod.POST) {
|
} else if (uri.equals("/banMultiple") && request.method() == HttpMethod.POST) {
|
||||||
banMultiple(request, responseWriter);
|
banMultiple(request, responseWriter);
|
||||||
} else if (uri.equals("/banUserTemp") && request.method() == HttpMethod.POST) {
|
} else if (uri.equals("/banUserTemp") && request.method() == HttpMethod.POST) {
|
||||||
@@ -161,6 +163,25 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
|
|||||||
return "OK";
|
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 {
|
private void banUser(HttpRequest request, ResponseWriter responseWriter) throws Exception {
|
||||||
validateAdmin(request);
|
validateAdmin(request);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gempukku.lotro.async.handler;
|
|||||||
import com.gempukku.lotro.async.HttpProcessingException;
|
import com.gempukku.lotro.async.HttpProcessingException;
|
||||||
import com.gempukku.lotro.async.ResponseWriter;
|
import com.gempukku.lotro.async.ResponseWriter;
|
||||||
import com.gempukku.lotro.game.Player;
|
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.HttpMethod;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
|
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);
|
Player player = _playerDao.loginUser(login, password);
|
||||||
if (player != null) {
|
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();
|
final Date bannedUntil = player.getBannedUntil();
|
||||||
if (bannedUntil != null && bannedUntil.after(new Date()))
|
if (bannedUntil != null && bannedUntil.after(new Date()))
|
||||||
throw new HttpProcessingException(409);
|
throw new HttpProcessingException(409);
|
||||||
|
|||||||
@@ -3,6 +3,15 @@
|
|||||||
|
|
||||||
|
|
||||||
<div id="banMain" class="article">
|
<div id="banMain" class="article">
|
||||||
|
<h1>Reset User Password</h1>
|
||||||
|
<div>
|
||||||
|
Name (case-sensitive): <input id="reset-input" type="text" ><br/>
|
||||||
|
<button id="reset-button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false" style="padding:4px;">
|
||||||
|
Reset Password
|
||||||
|
</button> <span id="reset-result" style="display:inline-block;">Ready.</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<h1>Ban User</h1>
|
<h1>Ban User</h1>
|
||||||
<h2>Permanently</h2>
|
<h2>Permanently</h2>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -53,6 +53,16 @@ var GempLotrCommunication = Class.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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) {
|
getGameHistory:function (start, count, callback, errorMap) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type:"GET",
|
type:"GET",
|
||||||
@@ -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) {
|
permabanUser:function (login, callback, errorMap) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type:"POST",
|
type:"POST",
|
||||||
@@ -1050,7 +1074,7 @@ var GempLotrCommunication = Class.extend({
|
|||||||
login:login,
|
login:login,
|
||||||
password:password,
|
password:password,
|
||||||
participantId:getUrlParam("participantId")},
|
participantId:getUrlParam("participantId")},
|
||||||
success:this.deliveryCheck(callback),
|
success:this.deliveryCheckStatus(callback),
|
||||||
error:this.errorCheck(errorMap),
|
error:this.errorCheck(errorMap),
|
||||||
dataType:"html"
|
dataType:"html"
|
||||||
});
|
});
|
||||||
@@ -1064,7 +1088,7 @@ var GempLotrCommunication = Class.extend({
|
|||||||
login:login,
|
login:login,
|
||||||
password:password,
|
password:password,
|
||||||
participantId:getUrlParam("participantId")},
|
participantId:getUrlParam("participantId")},
|
||||||
success:this.deliveryCheck(callback),
|
success:this.deliveryCheckStatus(callback),
|
||||||
error:this.errorCheck(errorMap),
|
error:this.errorCheck(errorMap),
|
||||||
dataType:"html"
|
dataType:"html"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
$("banMain").ready(
|
$("banMain").ready(
|
||||||
function () {
|
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(
|
$("#permaban-button").button().click(
|
||||||
function () {
|
function () {
|
||||||
let resultdiv = $("#permaban-result");
|
let resultdiv = $("#permaban-result");
|
||||||
|
|||||||
@@ -10,14 +10,22 @@ function register() {
|
|||||||
if (password != password2) {
|
if (password != password2) {
|
||||||
$(".error").html("Password and Password repeated are different! Try again");
|
$(".error").html("Password and Password repeated are different! Try again");
|
||||||
} else {
|
} else {
|
||||||
comm.register(login, password, function () {
|
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";
|
location.href = "/gemp-lotr/hall.html";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"0": function () {
|
"0": function () {
|
||||||
alert("Unable to connect to server, either server is down or there is a problem" +
|
alert("Unable to connect to server, either server is down or there is a problem" +
|
||||||
" with your internet connection");
|
" with your internet connection");
|
||||||
},
|
},
|
||||||
|
"202": function () {
|
||||||
|
$(".error").html("Your password has successfully been reset! Please refresh the page and log in.");
|
||||||
|
},
|
||||||
"400": function () {
|
"400": function () {
|
||||||
$(".error").html("Login is invalid. Login must be between 2-10 characters long, and contain only<br/>" +
|
$(".error").html("Login is invalid. Login must be between 2-10 characters long, and contain only<br/>" +
|
||||||
" english letters, numbers or _ (underscore) and - (dash) characters.");
|
" english letters, numbers or _ (underscore) and - (dash) characters.");
|
||||||
@@ -45,24 +53,38 @@ function registrationScreen() {
|
|||||||
function login() {
|
function login() {
|
||||||
var login = $("#login").val();
|
var login = $("#login").val();
|
||||||
var password = $("#password").val();
|
var password = $("#password").val();
|
||||||
comm.login(login, password, function () {
|
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";
|
location.href = "/gemp-lotr/hall.html";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"0": function () {
|
"0": function () {
|
||||||
alert("Unable to connect to server, either server is down or there is a problem" +
|
alert("Unable to connect to server, either server is down or there is a problem" +
|
||||||
" with your internet connection");
|
" 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 () {
|
"401": function () {
|
||||||
$(".error").html("Invalid username or password. Try again.");
|
$(".error").html("Invalid username or password. Try again.");
|
||||||
loginScreen();
|
loginScreen();
|
||||||
},
|
},
|
||||||
"403": function () {
|
"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 <a href='http://lotrtcgwiki.com/forums/'>TLHH forums</a>.");
|
$(".error").html("You have been permanently banned. If you think it was a mistake please appeal with dmaz or ketura on <a href='https://lotrtcgpc.net/discord>the PC Discord</a>.");
|
||||||
$(".interaction").html("");
|
$(".interaction").html("");
|
||||||
},
|
},
|
||||||
"409": function () {
|
"409": function () {
|
||||||
$(".error").html("You have been temporarily banned. You can try logging in at a later time. If you think it was a mistake you can try sending a private message to Merrick_H on <a href='http://lotrtcgwiki.com/forums/'>TLHH forums</a>.");
|
$(".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 <a href='https://lotrtcgpc.net/discord>the PC Discord</a>.");
|
||||||
$(".interaction").html("");
|
$(".interaction").html("");
|
||||||
},
|
},
|
||||||
"503": function () {
|
"503": function () {
|
||||||
@@ -92,6 +114,8 @@ function loginScreen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(".interaction").append(loginButton);
|
$(".interaction").append(loginButton);
|
||||||
|
|
||||||
|
$(".interaction").append("<br/><a href='https://lotrtcgpc.net/discord'>Forgot your password? Contact <span style='color:orange'>ketura</span> on the PC Discord.</a>");
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(
|
$(document).ready(
|
||||||
|
|||||||
@@ -64,6 +64,19 @@ public class DBDefs {
|
|||||||
public static class Player {
|
public static class Player {
|
||||||
public int id;
|
public int id;
|
||||||
public String name;
|
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 {
|
public static class FormatStats {
|
||||||
|
|||||||
@@ -1,8 +1,61 @@
|
|||||||
package com.gempukku.lotro.game;
|
package com.gempukku.lotro.game;
|
||||||
|
|
||||||
|
import com.gempukku.lotro.common.DBDefs;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Player {
|
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<Type> getTypes(String typeString) {
|
||||||
|
List<Type> types = new ArrayList<>();
|
||||||
|
for (Type type : values()) {
|
||||||
|
if (typeString.contains(type.getValue())) {
|
||||||
|
types.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getTypeString(List<Type> 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 int _id;
|
||||||
private final String _name;
|
private final String _name;
|
||||||
private final String _password;
|
private final String _password;
|
||||||
@@ -12,6 +65,10 @@ public class Player {
|
|||||||
private final String _createIp;
|
private final String _createIp;
|
||||||
private final String _lastIp;
|
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) {
|
public Player(int id, String name, String password, String type, Integer lastLoginReward, Date bannedUntil, String createIp, String lastIp) {
|
||||||
_id = id;
|
_id = id;
|
||||||
_name = name;
|
_name = name;
|
||||||
@@ -66,7 +123,7 @@ public class Player {
|
|||||||
|
|
||||||
Player player = (Player) o;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -76,15 +133,15 @@ public class Player {
|
|||||||
return _name != null ? _name.hashCode() : 0;
|
return _name != null ? _name.hashCode() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerDefinition GetUserInfo() {
|
public PlayerInfo GetUserInfo() {
|
||||||
return new PlayerDefinition(_name, _type);
|
return new PlayerInfo(_name, _type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlayerDefinition {
|
public class PlayerInfo {
|
||||||
public String name;
|
public String name;
|
||||||
public String type;
|
public String type;
|
||||||
|
|
||||||
public PlayerDefinition(String name, String info) {
|
public PlayerInfo(String name, String info) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
type = info;
|
type = info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ public class CachedPlayerDAO implements PlayerDAO, Cached {
|
|||||||
return _playerById.size() + _playerByName.size();
|
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
|
@Override
|
||||||
public boolean banPlayerPermanently(String login) throws SQLException {
|
public boolean banPlayerPermanently(String login) throws SQLException {
|
||||||
final boolean success = _delegate.banPlayerPermanently(login);
|
final boolean success = _delegate.banPlayerPermanently(login);
|
||||||
|
|||||||
@@ -13,7 +13,19 @@ import java.util.*;
|
|||||||
|
|
||||||
public class DbPlayerDAO implements PlayerDAO {
|
public class DbPlayerDAO implements PlayerDAO {
|
||||||
private final String validLoginChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
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;
|
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
|
@Override
|
||||||
public boolean banPlayerPermanently(String login) throws SQLException {
|
public boolean banPlayerPermanently(String login) throws SQLException {
|
||||||
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
||||||
@@ -152,17 +187,29 @@ public class DbPlayerDAO implements PlayerDAO {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Player loginUser(String login, String password) throws SQLException {
|
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=?")) {
|
try {
|
||||||
statement.setString(1, login);
|
Sql2o db = new Sql2o(_dbAccess.getDataSource());
|
||||||
statement.setString(2, encodePassword(password));
|
|
||||||
try (ResultSet rs = statement.executeQuery()) {
|
try (org.sql2o.Connection conn = db.open()) {
|
||||||
if (rs.next()) {
|
String sql = _selectPlayer +
|
||||||
return getPlayerFromResultSet(rs);
|
"""
|
||||||
} else
|
WHERE name = :login
|
||||||
|
AND (password = :password OR password = '')
|
||||||
|
""";
|
||||||
|
List<DBDefs.Player> 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 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
|
@Override
|
||||||
public synchronized boolean registerUser(String login, String password, String remoteAddr) throws SQLException, LoginInvalidException {
|
public synchronized boolean registerUser(String login, String password, String remoteAddr) throws SQLException, LoginInvalidException {
|
||||||
boolean result = validateLogin(login);
|
if (!validLoginName(login))
|
||||||
if (!result)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try (Connection conn = _dbAccess.getDataSource().getConnection()) {
|
if(loginExists(login)) {
|
||||||
try (PreparedStatement statement = conn.prepareStatement("insert into player (name, password, type, create_ip) values (?, ?, ?, ?)")) {
|
if(!needsPasswordReset(login))
|
||||||
statement.setString(1, login);
|
return false;
|
||||||
statement.setString(2, encodePassword(password));
|
|
||||||
statement.setString(3, "u");
|
//Login exists but has a blank/null password, meaning this user is actually performing a password reset
|
||||||
statement.setString(4, remoteAddr);
|
try {
|
||||||
statement.execute();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Unable to update password", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateLogin(String login) throws SQLException, LoginInvalidException {
|
|
||||||
|
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 validLoginName(String login) throws LoginInvalidException {
|
||||||
if (login.length() < 2 || login.length() > 30)
|
if (login.length() < 2 || login.length() > 30)
|
||||||
throw new LoginInvalidException();
|
throw new LoginInvalidException();
|
||||||
for (int i = 0; i < login.length(); i++) {
|
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"))
|
if (lowerCase.startsWith("admin") || lowerCase.startsWith("guest") || lowerCase.startsWith("system") || lowerCase.startsWith("bye"))
|
||||||
return false;
|
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<DBDefs.Player> 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<DBDefs.Player> 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ public interface PlayerDAO {
|
|||||||
|
|
||||||
public Player getPlayer(String playerName);
|
public Player getPlayer(String playerName);
|
||||||
|
|
||||||
|
public boolean resetUserPassword(String login) throws SQLException;
|
||||||
|
|
||||||
public boolean banPlayerPermanently(String login) throws SQLException;
|
public boolean banPlayerPermanently(String login) throws SQLException;
|
||||||
|
|
||||||
public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException;
|
public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException;
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ public class AdminService {
|
|||||||
_loggedUserHolder = loggedUserHolder;
|
_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) {
|
public boolean banUser(String login) {
|
||||||
try {
|
try {
|
||||||
final boolean success = _playerDAO.banPlayerPermanently(login);
|
final boolean success = _playerDAO.banPlayerPermanently(login);
|
||||||
|
|||||||
Reference in New Issue
Block a user