Merge pull request #689 from AuthMe-Team/pre-injector

BETA2
This commit is contained in:
Gabriele C 2016-05-04 17:41:26 +02:00
commit 4016460c17
169 changed files with 3745 additions and 2925 deletions

View File

@ -3,13 +3,7 @@ sudo: false
language: java
jdk: oraclejdk7
cache:
directories:
- '$HOME/.m2/repository'
script:
- mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
- mvn clean install -B -U
script: mvn verify -B
notifications:
webhooks:

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:30 CET 2016. See commands/commands.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:20 CEST 2016. See commands/commands.tpl.md -->
## AuthMe Commands
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
@ -7,74 +7,72 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
- **/authme**: The main AuthMeReloaded command. The root for all admin commands.
- **/authme register** &lt;player> &lt;password>: Register the specified player with the specified password.
<br />Requires `authme.admin.register`
<br />Requires `authme.admin.register`
- **/authme unregister** &lt;player>: Unregister the specified player.
<br />Requires `authme.admin.unregister`
<br />Requires `authme.admin.unregister`
- **/authme forcelogin** [player]: Enforce the specified player to login.
<br />Requires `authme.player.canbeforced`
<br />Requires `authme.admin.forcelogin`
- **/authme password** &lt;player> &lt;pwd>: Change the password of a player.
<br />Requires `authme.admin.changepassword`
<br />Requires `authme.admin.changepassword`
- **/authme lastlogin** [player]: View the date of the specified players last login.
<br />Requires `authme.admin.lastlogin`
<br />Requires `authme.admin.lastlogin`
- **/authme accounts** [player]: Display all accounts of a player by his player name or IP.
<br />Requires `authme.admin.accounts`
<br />Requires `authme.admin.accounts`
- **/authme email** [player]: Display the email address of the specified player if set.
<br />Requires `authme.admin.getemail`
<br />Requires `authme.admin.getemail`
- **/authme setemail** &lt;player> &lt;email>: Change the email address of the specified player.
<br />Requires `authme.admin.changemail`
<br />Requires `authme.admin.changemail`
- **/authme getip** &lt;player>: Get the IP address of the specified online player.
<br />Requires `authme.admin.getip`
- **/authme spawn** &lt;player>: Teleport to the spawn.
<br />Requires `authme.admin.spawn`
<br />Requires `authme.admin.getip`
- **/authme spawn**: Teleport to the spawn.
<br />Requires `authme.admin.spawn`
- **/authme setspawn**: Change the player's spawn to your current position.
<br />Requires `authme.admin.setspawn`
<br />Requires `authme.admin.setspawn`
- **/authme firstspawn**: Teleport to the first spawn.
<br />Requires `authme.admin.firstspawn`
<br />Requires `authme.admin.firstspawn`
- **/authme setfirstspawn**: Change the first player's spawn to your current position.
<br />Requires `authme.admin.setfirstspawn`
<br />Requires `authme.admin.setfirstspawn`
- **/authme purge** &lt;days>: Purge old AuthMeReloaded data longer than the specified amount of days ago.
<br />Requires `authme.admin.purge`
<br />Requires `authme.admin.purge`
- **/authme resetpos** &lt;player/*>: Purge the last know position of the specified player or all of them.
<br />Requires `authme.admin.purgelastpos`
<br />Requires `authme.admin.purgelastpos`
- **/authme purgebannedplayers**: Purge all AuthMeReloaded data for banned players.
<br />Requires `authme.admin.purgebannedplayers`
<br />Requires `authme.admin.purgebannedplayers`
- **/authme switchantibot** [mode]: Switch or toggle the AntiBot mode to the specified state.
<br />Requires `authme.admin.switchantibot`
<br />Requires `authme.admin.switchantibot`
- **/authme reload**: Reload the AuthMeReloaded plugin.
<br />Requires `authme.admin.reload`
<br />Requires `authme.admin.reload`
- **/authme version**: Show detailed information about the installed AuthMeReloaded version, the developers, contributors, and license.
- **/authme converter** &lt;job>: Converter command for AuthMeReloaded.
<br />Requires `authme.admin.converter`
- **/authme help** [query]: View detailed help for /authme commands.
- **/login** &lt;password>: Command to log in using AuthMeReloaded.
<br />Requires `authme.player.login`
<br />Requires `authme.player.login`
- **/login help** [query]: View detailed help for /login commands.
- **/logout**: Command to logout using AuthMeReloaded.
<br />Requires `authme.player.logout`
<br />Requires `authme.player.logout`
- **/logout help** [query]: View detailed help for /logout commands.
- **/register** [password] [verifyPassword]: Command to register using AuthMeReloaded.
<br />Requires `authme.player.register`
<br />Requires `authme.player.register`
- **/register help** [query]: View detailed help for /register commands.
- **/unreg** &lt;password>: Command to unregister using AuthMeReloaded.
<br />Requires `authme.player.unregister`
<br />Requires `authme.player.unregister`
- **/unreg help** [query]: View detailed help for /unreg commands.
- **/changepassword** &lt;oldPassword> &lt;newPassword>: Command to change your password using AuthMeReloaded.
<br />Requires `authme.player.changepassword`
<br />Requires `authme.player.changepassword`
- **/changepassword help** [query]: View detailed help for /changepassword commands.
- **/email**: The AuthMeReloaded Email command base.
- **/email add** &lt;email> &lt;verifyEmail>: Add a new email address to your account.
<br />Requires `authme.player.email.add`
<br />Requires `authme.player.email.add`
- **/email change** &lt;oldEmail> &lt;newEmail>: Change an email address of your account.
<br />Requires `authme.player.email.change`
<br />Requires `authme.player.email.change`
- **/email recover** &lt;email>: Recover your account using an Email address by sending a mail containing a new password.
<br />Requires `authme.player.email.recover`
<br />Requires `authme.player.email.recover`
- **/email help** [query]: View detailed help for /email commands.
- **/captcha** &lt;captcha>: Captcha command for AuthMeReloaded.
<br />Requires `authme.player.captcha`
<br />Requires `authme.player.captcha`
- **/captcha help** [query]: View detailed help for /captcha commands.
- **/converter** &lt;job>: Converter command for AuthMeReloaded.
<br />Requires `authme.admin.converter`
- **/converter help** [query]: View detailed help for /converter commands.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:30 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:20 CEST 2016

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:32 CET 2016. See hashmethods/hash_algorithms.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:22 CEST 2016. See hashmethods/hash_algorithms.tpl.md -->
## Hash Algorithms
AuthMe supports the following hash algorithms for storing your passwords safely.
@ -17,7 +17,7 @@ JOOMLA | Recommended | 65 | | | Text | 32 |
MD5 | Do not use | 32 | | | None | |
MD5VB | Acceptable | 56 | | | Text | 16 |
MYBB | Acceptable | 32 | | | Text | 8 | Y
PBKDF2 | Does not work | 330 | | | Text | 12 |
PBKDF2 | Does not work | 328 | | | Text | 12 |
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
PHPBB | Acceptable | 34 | | | Text | 16 |
PHPFUSION | Do not use | 64 | Y | | | | Y
@ -82,4 +82,4 @@ or bad.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:32 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:22 CEST 2016

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sun Feb 14 19:00:34 CET 2016. See permissions/permission_nodes.tpl.md -->
<!-- File auto-generated on Thu Apr 07 17:17:24 CEST 2016. See permissions/permission_nodes.tpl.md -->
## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds.
@ -42,7 +42,6 @@ The following are the permission nodes that are currently supported by the lates
- **authme.player.unregister** Command permission to unregister.
- **authme.vip** Permission node to identify VIP users.
---
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Sun Feb 14 19:00:34 CET 2016
This page was automatically generated on the [AuthMe-Team/AuthMeReloaded repository](https://github.com/AuthMe-Team/AuthMeReloaded/tree/master/docs/) on Thu Apr 07 17:17:24 CEST 2016

21
pom.xml
View File

@ -6,11 +6,11 @@
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.2-SNAPSHOT</version>
<version>5.2-BETA2</version>
<packaging>jar</packaging>
<name>AuthMeReloaded</name>
<description>Authentication plugin for CraftBukkit/Spigot!</description>
<description>The first authentication plugin for the Bukkit API!</description>
<inceptionYear>2013</inceptionYear>
<url>http://dev.bukkit.org/bukkit-plugins/authme-reloaded/</url>
<!-- See also: https://www.spigotmc.org/resources/authme-reloaded.6269/ -->
@ -23,7 +23,7 @@
<scm>
<connection>scm:git:https://github.com/Xephi/AuthMeReloaded.git</connection>
<developerConnection>scm:git:git@github.com:Xephi/AuthMeReloaded.git</developerConnection>
<url>http://github.com/Xephi/AuthMeReloaded</url>
<url>https://github.com/Xephi/AuthMeReloaded</url>
</scm>
<ciManagement>
@ -40,6 +40,7 @@
<license>
<name>The GNU General Public Licence version 3 (GPLv3)</name>
<url>http://www.gnu.org/licenses/gpl-3.0.html</url>
<distribution>repo</distribution>
</license>
</licenses>
@ -63,7 +64,7 @@
<buildNumber>Unknown</buildNumber>
<!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.9-R0.1-SNAPSHOT</bukkitVersion>
<bukkitVersion>1.9.2-R0.1-SNAPSHOT</bukkitVersion>
</properties>
<!-- Jenkins profile (add the real buildNumber to the version string) -->
@ -336,7 +337,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.5</version>
<version>2.4.6</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@ -349,7 +350,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.20</version>
<version>1.7.21</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@ -428,6 +429,14 @@
<optional>true</optional>
</dependency>
<!--Spigot API-->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.9.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Bukkit API, http://www.spigotmc.org/ or http://bukkit.org/ -->
<dependency>
<groupId>org.bukkit</groupId>

View File

@ -1,8 +1,34 @@
package fr.xephi.authme;
import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_ACCOUNT;
import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_PASSWORD;
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import fr.xephi.authme.api.API;
import fr.xephi.authme.api.NewAPI;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.backup.JsonCache;
@ -28,6 +54,7 @@ import fr.xephi.authme.listener.AuthMeInventoryPacketAdapter;
import fr.xephi.authme.listener.AuthMePlayerListener;
import fr.xephi.authme.listener.AuthMePlayerListener16;
import fr.xephi.authme.listener.AuthMePlayerListener18;
import fr.xephi.authme.listener.AuthMePlayerListener19;
import fr.xephi.authme.listener.AuthMeServerListener;
import fr.xephi.authme.listener.AuthMeTabCompletePacketAdapter;
import fr.xephi.authme.listener.AuthMeTablistPacketAdapter;
@ -62,32 +89,7 @@ import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.util.MigrationService;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils;
import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_ACCOUNT;
import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_PASSWORD;
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
import fr.xephi.authme.util.ValidationService;
/**
* The AuthMe main class.
@ -106,23 +108,25 @@ public class AuthMe extends JavaPlugin {
private static Server server;
/*
* Maps and stuff
* TODO: Clean up and Move into a manager
*/
// TODO #601: Integrate CaptchaManager
public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>();
/*
* Public Instances
* TODO #432: Encapsulation
*/
public NewAPI api;
// TODO #655: Encapsulate mail
public SendMailSSL mail;
// TODO #656: Encapsulate data manager
public DataManager dataManager;
/*
* Plugin Hooks
* TODO: Move into modules
* Private instances
* TODO #432: Move instantiation and management of these services
*/
// TODO #604: Encapsulate ProtocolLib members
public AuthMeInventoryPacketAdapter inventoryProtector;
public AuthMeTabCompletePacketAdapter tabComplete;
public AuthMeTablistPacketAdapter tablistHider;
@ -134,11 +138,11 @@ public class AuthMe extends JavaPlugin {
private JsonCache playerBackup;
private PasswordSecurity passwordSecurity;
private DataSource database;
private IpAddressManager ipAddressManager;
private PluginHooks pluginHooks;
private SpawnLoader spawnLoader;
private AntiBot antiBot;
private boolean autoPurging;
private BukkitService bukkitService;
/**
* Get the plugin's instance.
@ -248,24 +252,19 @@ public class AuthMe extends JavaPlugin {
return;
}
bukkitService = new BukkitService(this);
pluginHooks = new PluginHooks(server.getPluginManager());
MigrationService.changePlainTextToSha256(newSettings, database, new SHA256());
passwordSecurity = new PasswordSecurity(getDataSource(), newSettings, Bukkit.getPluginManager());
ipAddressManager = new IpAddressManager(newSettings);
// Initialize spawn loader
spawnLoader = new SpawnLoader(getDataFolder(), newSettings, pluginHooks);
// Set up the permissions manager and command handler
permsMan = initializePermissionsManager();
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings, ipAddressManager,
pluginHooks, spawnLoader, antiBot);
// AntiBot delay
BukkitService bukkitService = new BukkitService(this);
antiBot = new AntiBot(newSettings, messages, permsMan, bukkitService);
ValidationService validationService = new ValidationService(newSettings, database, permsMan);
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings,
pluginHooks, spawnLoader, antiBot, validationService, bukkitService);
// Set up Metrics
MetricsStarter.setupMetrics(plugin, newSettings);
@ -292,24 +291,25 @@ public class AuthMe extends JavaPlugin {
playerBackup = new JsonCache();
// Set the DataManager
dataManager = new DataManager(this, pluginHooks);
dataManager = new DataManager(this, pluginHooks, bukkitService);
// Set up the new API
setupApi();
// Set up the management
ProcessService processService = new ProcessService(newSettings, messages, this, database, ipAddressManager,
passwordSecurity, pluginHooks, spawnLoader);
ProcessService processService = new ProcessService(newSettings, messages, this, database,
passwordSecurity, pluginHooks, spawnLoader, validationService, bukkitService);
management = new Management(this, processService, database, PlayerCache.getInstance());
// Set up the BungeeCord hook
setupBungeeCordHook(newSettings, ipAddressManager);
setupBungeeCordHook(newSettings);
// Reload support hook
reloadSupportHook();
// Register event listeners
registerEventListeners(messages, database, management, pluginHooks, spawnLoader, antiBot);
registerEventListeners(
messages, database, management, pluginHooks, spawnLoader, antiBot, bukkitService, validationService);
// Start Email recall task if needed
scheduleRecallEmailTask();
@ -317,7 +317,6 @@ public class AuthMe extends JavaPlugin {
showSettingsWarnings();
// Sponsor messages
ConsoleLogger.info("AuthMe hooks perfectly with the VeryGames server hosting!");
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
ConsoleLogger.info("Do you want a good game server? Look at our sponsor GameHosting.it leader in Italy as Game Server Provider!");
@ -341,7 +340,7 @@ public class AuthMe extends JavaPlugin {
}
database.reload();
messages.reload(newSettings.getMessagesFile());
passwordSecurity.reload(newSettings);
passwordSecurity.reload();
spawnLoader.initialize(newSettings);
}
@ -375,15 +374,18 @@ public class AuthMe extends JavaPlugin {
* Register all event listeners.
*/
private void registerEventListeners(Messages messages, DataSource dataSource, Management management,
PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot) {
PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot,
BukkitService bukkitService, ValidationService validationService) {
// Get the plugin manager instance
PluginManager pluginManager = server.getPluginManager();
// Register event listeners
pluginManager.registerEvents(new AuthMePlayerListener(this, messages, dataSource, antiBot, management), this);
pluginManager.registerEvents(new AuthMePlayerListener(
this, newSettings, messages, dataSource, antiBot, management, bukkitService, validationService), this);
pluginManager.registerEvents(new AuthMeBlockListener(), this);
pluginManager.registerEvents(new AuthMeEntityListener(), this);
pluginManager.registerEvents(new AuthMeServerListener(this, messages, pluginHooks, spawnLoader), this);
pluginManager.registerEvents(new AuthMeServerListener(
this, messages, newSettings, pluginHooks, spawnLoader, validationService), this);
// Try to register 1.6 player listeners
try {
@ -398,11 +400,18 @@ public class AuthMe extends JavaPlugin {
pluginManager.registerEvents(new AuthMePlayerListener18(), this);
} catch (ClassNotFoundException ignore) {
}
// Try to register 1.9 player listeners
try {
Class.forName("org.spigotmc.event.player.PlayerSpawnLocationEvent");
pluginManager.registerEvents(new AuthMePlayerListener19(this), this);
} catch (ClassNotFoundException ignore) {
}
}
private void reloadSupportHook() {
if (database != null) {
int playersOnline = Utils.getOnlinePlayers().size();
int playersOnline = bukkitService.getOnlinePlayers().size();
if (playersOnline < 1) {
database.purgeLogged();
} else if (Settings.reloadSupport) {
@ -421,23 +430,23 @@ public class AuthMe extends JavaPlugin {
/**
* Set up the BungeeCord hook.
*/
private void setupBungeeCordHook(NewSetting settings, IpAddressManager ipAddressManager) {
private void setupBungeeCordHook(NewSetting settings) {
if (settings.getProperty(HooksSettings.BUNGEECORD)) {
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
Bukkit.getMessenger().registerIncomingPluginChannel(
this, "BungeeCord", new BungeeCordMessage(this, ipAddressManager));
this, "BungeeCord", new BungeeCordMessage(this));
}
}
private CommandHandler initializeCommandHandler(PermissionsManager permissionsManager, Messages messages,
PasswordSecurity passwordSecurity, NewSetting settings,
IpAddressManager ipAddressManager, PluginHooks pluginHooks,
SpawnLoader spawnLoader, AntiBot antiBot) {
PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot,
ValidationService validationService, BukkitService bukkitService) {
HelpProvider helpProvider = new HelpProvider(permissionsManager, settings.getProperty(HELP_HEADER));
Set<CommandDescription> baseCommands = CommandInitializer.buildCommands();
CommandMapper mapper = new CommandMapper(baseCommands, permissionsManager);
CommandService commandService = new CommandService(this, mapper, helpProvider, messages, passwordSecurity,
permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader, antiBot);
permissionsManager, settings, pluginHooks, spawnLoader, antiBot, validationService, bukkitService);
return new CommandHandler(commandService);
}
@ -501,9 +510,11 @@ public class AuthMe extends JavaPlugin {
@Override
public void onDisable() {
// Save player data
Collection<? extends Player> players = Utils.getOnlinePlayers();
for (Player player : players) {
savePlayer(player);
if (bukkitService != null) {
Collection<? extends Player> players = bukkitService.getOnlinePlayers();
for (Player player : players) {
savePlayer(player);
}
}
// Do backup on stop if enabled
@ -616,7 +627,7 @@ public class AuthMe extends JavaPlugin {
* Set up the permissions manager.
*/
private PermissionsManager initializePermissionsManager() {
PermissionsManager manager = new PermissionsManager(Bukkit.getServer(), this, getLogger());
PermissionsManager manager = new PermissionsManager(Bukkit.getServer(), getLogger());
manager.setup();
return manager;
}
@ -662,7 +673,7 @@ public class AuthMe extends JavaPlugin {
tabComplete = null;
}
if (newSettings.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && tablistHider == null) {
tablistHider = new AuthMeTablistPacketAdapter(this);
tablistHider = new AuthMeTablistPacketAdapter(this, bukkitService);
tablistHider.register();
} else if (tablistHider != null) {
tablistHider.unregister();
@ -759,8 +770,8 @@ public class AuthMe extends JavaPlugin {
public void run() {
for (PlayerAuth auth : database.getLoggedPlayers()) {
String email = auth.getEmail();
if (StringUtils.isEmpty(email) || email.equalsIgnoreCase("your@email.com")) {
Player player = Utils.getPlayer(auth.getRealName());
if (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email)) {
Player player = bukkitService.getPlayerExact(auth.getRealName());
if (player != null) {
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
}
@ -771,8 +782,8 @@ public class AuthMe extends JavaPlugin {
}
public String replaceAllInfo(String message, Player player) {
String playersOnline = Integer.toString(Utils.getOnlinePlayers().size());
String ipAddress = ipAddressManager.getPlayerIp(player);
String playersOnline = Integer.toString(bukkitService.getOnlinePlayers().size());
String ipAddress = Utils.getPlayerIp(player);
return message
.replace("&", "\u00a7")
.replace("{PLAYER}", player.getName())
@ -788,8 +799,8 @@ public class AuthMe extends JavaPlugin {
public boolean isLoggedIp(String name, String ip) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(ipAddressManager.getPlayerIp(player))
for (Player player : bukkitService.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(Utils.getPlayerIp(player))
&& database.isLogged(player.getName().toLowerCase())
&& !player.getName().equalsIgnoreCase(name)) {
++count;

View File

@ -3,10 +3,10 @@ package fr.xephi.authme;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.settings.properties.PurgeSettings;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.ArrayList;
@ -18,16 +18,15 @@ public class DataManager {
private final AuthMe plugin;
private final PluginHooks pluginHooks;
private final BukkitService bukkitService;
/**
* Constructor for DataManager.
*
* @param plugin The plugin instance
* @param pluginHooks Plugin hooks instance
/*
* Constructor.
*/
public DataManager(AuthMe plugin, PluginHooks pluginHooks) {
public DataManager(AuthMe plugin, PluginHooks pluginHooks, BukkitService bukkitService) {
this.plugin = plugin;
this.pluginHooks = pluginHooks;
this.bukkitService = bukkitService;
}
private List<OfflinePlayer> getOfflinePlayers(List<String> names) {
@ -64,6 +63,9 @@ public class DataManager {
int i = 0;
File dataFolder = new File("." + File.separator + "plugins" + File.separator + "LimitedCreative"
+ File.separator + "inventories");
if (!dataFolder.exists() || !dataFolder.isDirectory()) {
return;
}
for (String file : dataFolder.list()) {
String name = file;
int idx;
@ -123,6 +125,9 @@ public class DataManager {
}
final File userDataFolder = new File(essentialsDataFolder, "userdata");
if (!userDataFolder.exists() || !userDataFolder.isDirectory()) {
return;
}
List<OfflinePlayer> offlinePlayers = getOfflinePlayers(cleared);
for (OfflinePlayer player : offlinePlayers) {
File playerFile = new File(userDataFolder, Utils.getUUIDorName(player) + ".yml");
@ -143,21 +148,9 @@ public class DataManager {
ConsoleLogger.showError("Unable to access permissions manager instance!");
return;
}
int i = 0;
for (String name : cleared) {
permsMan.removeAllGroups(getOnlinePlayerLower(name));
i++;
permsMan.removeAllGroups(bukkitService.getPlayerExact(name));
}
ConsoleLogger.info("AutoPurge: Removed permissions from " + i + " player(s).");
}
private Player getOnlinePlayerLower(String name) {
name = name.toLowerCase();
for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(name)) {
return player;
}
}
return null;
ConsoleLogger.info("AutoPurge: Removed permissions from " + cleared.size() + " player(s).");
}
}

View File

@ -1,99 +0,0 @@
package fr.xephi.authme.cache;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
/**
* Stateful manager for looking up IP address appropriately, including caching.
*/
public class IpAddressManager {
/** Whether or not to use the VeryGames API for IP lookups. */
private final boolean useVeryGamesIpCheck;
/** Cache for lookups via the VeryGames API. */
private final ConcurrentHashMap<String, String> ipCache;
/**
* Constructor.
*
* @param settings The settings instance
*/
public IpAddressManager(NewSetting settings) {
this.useVeryGamesIpCheck = settings.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
this.ipCache = new ConcurrentHashMap<>();
}
/**
* Return the player's IP address. If enabled in the settings, the IP address returned by the
* VeryGames API will be returned.
*
* @param player The player to look up
* @return The IP address of the player
*/
public String getPlayerIp(Player player) {
if (useVeryGamesIpCheck) {
final String playerName = player.getName().toLowerCase();
final String cachedValue = ipCache.get(playerName);
if (cachedValue != null) {
return cachedValue;
}
final String plainIp = player.getAddress().getAddress().getHostAddress();
String veryGamesResult = getVeryGamesIp(plainIp, player.getAddress().getPort());
if (veryGamesResult != null) {
ipCache.put(playerName, veryGamesResult);
return veryGamesResult;
}
}
return player.getAddress().getAddress().getHostAddress();
}
/**
* Add a player to the IP address cache.
*
* @param player The player to add or update the cache entry for
* @param ip The IP address to add
*/
public void addCache(String player, String ip) {
if (useVeryGamesIpCheck) {
ipCache.put(player.toLowerCase(), ip);
}
}
/**
* Remove a player's cache entry.
*
* @param player The player to remove
*/
public void removeCache(String player) {
if (useVeryGamesIpCheck) {
ipCache.remove(player.toLowerCase());
}
}
// returns null if IP could not be looked up
private String getVeryGamesIp(final String plainIp, final int port) {
final String sUrl = String.format("http://monitor-1.verygames.net/api/?action=ipclean-real-ip"
+ "&out=raw&ip=%s&port=%d", plainIp, port);
try {
String result = Resources.toString(new URL(sUrl), Charsets.UTF_8);
if (!StringUtils.isEmpty(result) && !result.contains("error")) {
return result;
}
} catch (IOException e) {
ConsoleLogger.logException("Could not fetch Very Games API with URL '" + sUrl + "':", e);
}
return null;
}
}

View File

@ -10,8 +10,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.Settings;
import org.bukkit.entity.Player;
import java.io.File;
@ -24,7 +24,7 @@ public class JsonCache {
private final File cacheDir;
public JsonCache() {
cacheDir = Settings.CACHE_FOLDER;
cacheDir = new File(AuthMe.getInstance().getDataFolder(), "cache");
if (!cacheDir.exists() && !cacheDir.isDirectory() && !cacheDir.mkdir()) {
ConsoleLogger.showError("Failed to create cache directory.");
}

View File

@ -271,7 +271,7 @@ public final class CommandInitializer {
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("converter", "convert", "conv")
.description("Converter Command")
.description("Converter command")
.detailedDescription("Converter command for AuthMeReloaded.")
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " +
"royalauth / vauth / sqlitetosql", false)

View File

@ -5,7 +5,6 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
@ -15,8 +14,12 @@ import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.List;
/**
@ -32,29 +35,19 @@ public class CommandService {
private final PasswordSecurity passwordSecurity;
private final PermissionsManager permissionsManager;
private final NewSetting settings;
private final IpAddressManager ipAddressManager;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
private final AntiBot antiBot;
private final ValidationService validationService;
private final BukkitService bukkitService;
/**
/*
* Constructor.
*
* @param authMe The plugin instance
* @param commandMapper Command mapper
* @param helpProvider Help provider
* @param messages Messages instance
* @param passwordSecurity The Password Security instance
* @param permissionsManager The permissions manager
* @param settings The settings manager
* @param ipAddressManager The IP address manager
* @param pluginHooks The plugin hooks instance
* @param spawnLoader The spawn loader
*/
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
PasswordSecurity passwordSecurity, PermissionsManager permissionsManager, NewSetting settings,
IpAddressManager ipAddressManager, PluginHooks pluginHooks, SpawnLoader spawnLoader,
AntiBot antiBot) {
PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot,
ValidationService validationService, BukkitService bukkitService) {
this.authMe = authMe;
this.messages = messages;
this.helpProvider = helpProvider;
@ -62,10 +55,11 @@ public class CommandService {
this.passwordSecurity = passwordSecurity;
this.permissionsManager = permissionsManager;
this.settings = settings;
this.ipAddressManager = ipAddressManager;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
this.antiBot = antiBot;
this.validationService = validationService;
this.bukkitService = bukkitService;
}
/**
@ -199,10 +193,6 @@ public class CommandService {
return settings;
}
public IpAddressManager getIpAddressManager() {
return ipAddressManager;
}
public PlayerCache getPlayerCache() {
return PlayerCache.getInstance();
}
@ -219,4 +209,35 @@ public class CommandService {
return antiBot;
}
/**
* Verifies whether a password is valid according to the plugin settings.
*
* @param password the password to verify
* @param username the username the password is associated with
* @return message key with the password error, or {@code null} if password is valid
*/
public MessageKey validatePassword(String password, String username) {
return validationService.validatePassword(password, username);
}
public boolean validateEmail(String email) {
return validationService.validateEmail(email);
}
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
return validationService.isEmailFreeForRegistration(email, sender);
}
public Player getPlayer(String name) {
return bukkitService.getPlayerExact(name);
}
public Collection<? extends Player> getOnlinePlayers() {
return bukkitService.getOnlinePlayers();
}
public BukkitService getBukkitService() {
return bukkitService;
}
}

View File

@ -7,8 +7,6 @@ import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.CommandSender;
import java.util.List;
@ -22,30 +20,16 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
public void executeCommand(final CommandSender sender, List<String> arguments,
final CommandService commandService) {
// Get the player and password
String playerName = arguments.get(0);
final String playerName = arguments.get(0);
final String playerPass = arguments.get(1);
// Validate the password
String playerPassLowerCase = playerPass.toLowerCase();
if (!playerPassLowerCase.matches(commandService.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
return;
}
if (playerPassLowerCase.equalsIgnoreCase(playerName)) {
commandService.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
return;
}
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
return;
}
// TODO #602 20160312: The UNSAFE_PASSWORDS should be all lowercase
// -> introduce a lowercase String list property type
if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) {
commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
MessageKey passwordError = commandService.validatePassword(playerPass, playerName);
if (passwordError != null) {
commandService.send(sender, passwordError);
return;
}
// Set the password
final String playerNameLowerCase = playerName.toLowerCase();
commandService.runTaskAsynchronously(new Runnable() {

View File

@ -2,13 +2,13 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import static fr.xephi.authme.permission.PlayerPermission.CAN_LOGIN_BE_FORCED;
/**
* Forces the login of a player, i.e. logs the player in without the need of a (correct) password.
*/
@ -19,15 +19,14 @@ public class ForceLoginCommand implements ExecutableCommand {
// Get the player query
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
Player player = Utils.getPlayer(playerName);
Player player = commandService.getPlayer(playerName);
if (player == null || !player.isOnline()) {
sender.sendMessage("Player needs to be online!");
} else if (!commandService.getPermissionsManager()
.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)) {
sender.sendMessage("You cannot force login for the player " + playerName + "!");
} else if (!commandService.getPermissionsManager().hasPermission(player, CAN_LOGIN_BE_FORCED)) {
sender.sendMessage("You cannot force login the player " + playerName + "!");
} else {
commandService.getManagement().performLogin(player, "dontneed", true);
sender.sendMessage("Force Login for " + playerName + " performed!");
sender.sendMessage("Force login for " + playerName + " performed!");
}
}
}

View File

@ -2,8 +2,6 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -14,9 +12,9 @@ public class GetIpCommand implements ExecutableCommand {
@Override
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
// Get the player query
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
String playerName = arguments.get(0);
Player player = Utils.getPlayer(playerName);
Player player = commandService.getPlayer(playerName);
if (player == null) {
sender.sendMessage("The player is not online");
return;
@ -24,10 +22,5 @@ public class GetIpCommand implements ExecutableCommand {
sender.sendMessage(player.getName() + "'s IP is: " + player.getAddress().getAddress().getHostAddress()
+ ":" + player.getAddress().getPort());
if (commandService.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)) {
sender.sendMessage(player.getName() + "'s real IP is: "
+ commandService.getIpAddressManager().getPlayerIp(player));
}
}
}

View File

@ -1,17 +1,16 @@
package fr.xephi.authme.command.executable.authme;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import java.util.List;
/**
* Admin command to register a user.
@ -25,26 +24,14 @@ public class RegisterAdminCommand implements ExecutableCommand {
final String playerName = arguments.get(0);
final String playerPass = arguments.get(1);
final String playerNameLowerCase = playerName.toLowerCase();
final String playerPassLowerCase = playerPass.toLowerCase();
// Command logic
if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
return;
}
if (playerPassLowerCase.equalsIgnoreCase(playerName)) {
commandService.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
return;
}
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
return;
}
if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) {
commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
MessageKey passwordError = commandService.validatePassword(playerPass, playerName);
if (passwordError != null) {
commandService.send(sender, passwordError);
return;
}
commandService.runTaskAsynchronously(new Runnable() {
@Override
@ -66,11 +53,18 @@ public class RegisterAdminCommand implements ExecutableCommand {
return;
}
commandService.getDataSource().setUnlogged(playerNameLowerCase);
if (Bukkit.getPlayerExact(playerName) != null) {
Bukkit.getPlayerExact(playerName).kickPlayer("An admin just registered you, please log again");
} else {
commandService.send(sender, MessageKey.REGISTER_SUCCESS);
ConsoleLogger.info(playerName + " registered");
commandService.send(sender, MessageKey.REGISTER_SUCCESS);
ConsoleLogger.info(sender.getName() + " registered " + playerName);
Player player = commandService.getPlayer(playerName);
if (player != null) {
final Player p = player;
p.getServer().getScheduler().scheduleSyncDelayedTask(commandService.getAuthMe(), new Runnable() {
@Override
public void run() {
p.kickPlayer("An admin just registered you, please log in again");
}
});
}
}
});

View File

@ -4,12 +4,15 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import java.util.List;
/**
* Admin command for setting an email to an account.
*/
public class SetEmailCommand implements ExecutableCommand {
@Override
@ -20,7 +23,7 @@ public class SetEmailCommand implements ExecutableCommand {
final String playerEmail = arguments.get(1);
// Validate the email address
if (!Utils.isEmailCorrect(playerEmail, commandService.getSettings())) {
if (!commandService.validateEmail(playerEmail)) {
commandService.send(sender, MessageKey.INVALID_EMAIL);
return;
}
@ -29,18 +32,19 @@ public class SetEmailCommand implements ExecutableCommand {
@Override
public void run() {
// Validate the user
PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
DataSource dataSource = commandService.getDataSource();
PlayerAuth auth = dataSource.getAuth(playerName);
if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER);
return;
} else if (commandService.getDataSource().isEmailStored(playerEmail)) {
} else if (!commandService.isEmailFreeForRegistration(playerEmail, sender)) {
commandService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
return;
}
// Set the email address
auth.setEmail(playerEmail);
if (!commandService.getDataSource().updateEmail(auth)) {
if (!dataSource.updateEmail(auth)) {
commandService.send(sender, MessageKey.ERROR);
return;
}

View File

@ -7,31 +7,29 @@ import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.List;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
/**
* Admin command to unregister a player.
*/
public class UnregisterAdminCommand implements ExecutableCommand {
@Override
public void executeCommand(final CommandSender sender, List<String> arguments, CommandService commandService) {
// AuthMe plugin instance
final AuthMe plugin = AuthMe.getInstance();
// Get the player name
String playerName = arguments.get(0);
String playerNameLowerCase = playerName.toLowerCase();
@ -49,32 +47,48 @@ public class UnregisterAdminCommand implements ExecutableCommand {
}
// Unregister the player
Player target = Utils.getPlayer(playerNameLowerCase);
Player target = commandService.getPlayer(playerNameLowerCase);
PlayerCache.getInstance().removePlayer(playerNameLowerCase);
Utils.setGroup(target, Utils.GroupType.UNREGISTERED);
if (target != null && target.isOnline()) {
Utils.teleportToSpawn(target);
LimboCache.getInstance().addLimboPlayer(target);
int timeOut = Settings.getRegistrationTimeout * 20;
int interval = Settings.getWarnMessageInterval;
BukkitScheduler scheduler = sender.getServer().getScheduler();
if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTask(id);
}
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTask(
scheduler.runTask(
plugin, new MessageTask(plugin, playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)
)
);
if (commandService.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
if (commandService.getProperty(RegistrationSettings.FORCE)) {
applyUnregisteredEffectsAndTasks(target, commandService);
}
commandService.send(target, MessageKey.UNREGISTERED_SUCCESS);
}
// Show a status message
commandService.send(sender, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(playerName + " unregistered");
ConsoleLogger.info(sender.getName() + " unregistered " + playerName);
}
/**
* When registration is forced, applies the configured "unregistered effects" to the player as he
* would encounter when joining the server before logging on - reminder task to log in,
* timeout kick, blindness.
*
* @param target the player that was unregistered
* @param service the command service
*/
private void applyUnregisteredEffectsAndTasks(Player target, CommandService service) {
final AuthMe plugin = service.getAuthMe();
final BukkitService bukkitService = service.getBukkitService();
final String playerNameLowerCase = target.getName().toLowerCase();
Utils.teleportToSpawn(target);
LimboCache.getInstance().addLimboPlayer(target);
int timeOut = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
if (timeOut != 0) {
BukkitTask id = bukkitService.runTaskLater(new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTask(id);
}
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTask(
bukkitService.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)));
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
}
}
}

View File

@ -3,11 +3,11 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.util.Utils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.List;
import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
@ -22,11 +22,12 @@ public class VersionCommand implements ExecutableCommand {
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
sender.sendMessage(ChatColor.GOLD + "Developers:");
printDeveloper(sender, "Xephi", "xephi59", "Lead Developer");
printDeveloper(sender, "DNx5", "DNx5", "Developer");
printDeveloper(sender, "games647", "games647", "Developer");
printDeveloper(sender, "Tim Visee", "timvisee", "Developer");
printDeveloper(sender, "Sgdc3", "sgdc3", "Project manager, Contributor");
Collection<? extends Player> onlinePlayers = commandService.getOnlinePlayers();
printDeveloper(sender, "Xephi", "xephi59", "Lead Developer", onlinePlayers);
printDeveloper(sender, "DNx5", "DNx5", "Developer", onlinePlayers);
printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers);
printDeveloper(sender, "Tim Visee", "timvisee", "Developer", onlinePlayers);
printDeveloper(sender, "Sgdc3", "sgdc3", "Project manager, Contributor", onlinePlayers);
sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE +
"http://dev.bukkit.org/bukkit-plugins/authme-reloaded/");
sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0"
@ -38,12 +39,14 @@ public class VersionCommand implements ExecutableCommand {
/**
* Print a developer with proper styling.
*
* @param sender The command sender.
* @param name The display name of the developer.
* @param minecraftName The Minecraft username of the developer, if available.
* @param function The function of the developer.
* @param sender The command sender
* @param name The display name of the developer
* @param minecraftName The Minecraft username of the developer, if available
* @param function The function of the developer
* @param onlinePlayers The list of online players
*/
private static void printDeveloper(CommandSender sender, String name, String minecraftName, String function) {
private static void printDeveloper(CommandSender sender, String name, String minecraftName, String function,
Collection<? extends Player> onlinePlayers) {
// Print the name
StringBuilder msg = new StringBuilder();
msg.append(" ")
@ -55,7 +58,7 @@ public class VersionCommand implements ExecutableCommand {
msg.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (").append(function).append(")");
// Show the online status
if (isPlayerOnline(minecraftName)) {
if (isPlayerOnline(minecraftName, onlinePlayers)) {
msg.append(ChatColor.GREEN).append(ChatColor.ITALIC).append(" (In-Game)");
}
@ -66,12 +69,13 @@ public class VersionCommand implements ExecutableCommand {
/**
* Check whether a player is online.
*
* @param minecraftName The Minecraft player name.
* @param minecraftName The Minecraft player name
* @param onlinePlayers List of online players
*
* @return True if the player is online, false otherwise.
* @return True if the player is online, false otherwise
*/
private static boolean isPlayerOnline(String minecraftName) {
for (Player player : Utils.getOnlinePlayers()) {
private static boolean isPlayerOnline(String minecraftName, Collection<? extends Player> onlinePlayers) {
for (Player player : onlinePlayers) {
if (player.getName().equalsIgnoreCase(minecraftName)) {
return true;
}

View File

@ -5,8 +5,6 @@ import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.ChangePasswordTask;
import org.bukkit.entity.Player;
@ -30,22 +28,9 @@ public class ChangePasswordCommand extends PlayerCommand {
}
// Make sure the password is allowed
String playerPassLowerCase = newPassword.toLowerCase();
if (!playerPassLowerCase.matches(commandService.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return;
}
if (playerPassLowerCase.equalsIgnoreCase(name)) {
commandService.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR);
return;
}
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
commandService.send(player, MessageKey.INVALID_PASSWORD_LENGTH);
return;
}
if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) {
commandService.send(player, MessageKey.PASSWORD_UNSAFE_ERROR);
MessageKey passwordError = commandService.validatePassword(newPassword, name);
if (passwordError != null) {
commandService.send(player, passwordError);
return;
}

View File

@ -3,11 +3,13 @@ package fr.xephi.authme.command.executable.email;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
import java.util.List;
/**
* Command for setting an email to an account.
*/
public class AddEmailCommand extends PlayerCommand {
@Override
@ -15,9 +17,8 @@ public class AddEmailCommand extends PlayerCommand {
String email = arguments.get(0);
String emailConfirmation = arguments.get(1);
if (!Utils.isEmailCorrect(email, commandService.getSettings())) {
commandService.send(player, MessageKey.INVALID_EMAIL);
} else if (email.equals(emailConfirmation)) {
if (email.equals(emailConfirmation)) {
// Closer inspection of the mail address handled by the async task
commandService.getManagement().performAddEmail(player, email);
} else {
commandService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.command.executable.email;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
@ -9,7 +10,7 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.entity.Player;
@ -19,13 +20,12 @@ public class RecoverEmailCommand extends PlayerCommand {
@Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) {
String playerMail = arguments.get(0);
final String playerMail = arguments.get(0);
final String playerName = player.getName();
// Command logic
final AuthMe plugin = AuthMe.getInstance();
final AuthMe plugin = commandService.getAuthMe();
if (plugin.mail == null) {
ConsoleLogger.showError("Mail API is not set");
commandService.send(player, MessageKey.ERROR);
return;
}
@ -36,7 +36,7 @@ public class RecoverEmailCommand extends PlayerCommand {
return;
}
String thePass = RandomString.generate(Settings.getRecoveryPassLength);
String thePass = RandomString.generate(commandService.getProperty(EmailSettings.RECOVERY_PASSWORD_LENGTH));
HashedPassword hashNew = commandService.getPasswordSecurity().computeHash(thePass, playerName);
PlayerAuth auth;
if (PlayerCache.getInstance().isAuthenticated(playerName)) {
@ -47,13 +47,14 @@ public class RecoverEmailCommand extends PlayerCommand {
commandService.send(player, MessageKey.UNKNOWN_USER);
return;
}
if (StringUtils.isEmpty(Settings.getmailAccount)) {
if (StringUtils.isEmpty(commandService.getProperty(EmailSettings.MAIL_ACCOUNT))) {
ConsoleLogger.showError("No mail account set in settings");
commandService.send(player, MessageKey.ERROR);
return;
}
if (!playerMail.equalsIgnoreCase(auth.getEmail()) || playerMail.equalsIgnoreCase("your@email.com")
|| auth.getEmail().equalsIgnoreCase("your@email.com")) {
if (!playerMail.equalsIgnoreCase(auth.getEmail()) || "your@email.com".equalsIgnoreCase(playerMail)
|| "your@email.com".equalsIgnoreCase(auth.getEmail())) {
commandService.send(player, MessageKey.INVALID_EMAIL);
return;
}

View File

@ -1,19 +1,22 @@
package fr.xephi.authme.command.executable.register;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
import java.util.List;
import static fr.xephi.authme.settings.properties.EmailSettings.RECOVERY_PASSWORD_LENGTH;
import static fr.xephi.authme.settings.properties.RegistrationSettings.ENABLE_CONFIRM_EMAIL;
import static fr.xephi.authme.settings.properties.RegistrationSettings.USE_EMAIL_REGISTRATION;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION;
public class RegisterCommand extends PlayerCommand {
@Override
@ -24,39 +27,62 @@ public class RegisterCommand extends PlayerCommand {
return;
}
if (arguments.isEmpty() || Settings.enablePasswordConfirmation && arguments.size() < 2) {
// Ensure that there is 1 argument, or 2 if confirmation is required
final boolean useConfirmation = isConfirmationRequired(commandService);
if (arguments.isEmpty() || useConfirmation && arguments.size() < 2) {
commandService.send(player, MessageKey.USAGE_REGISTER);
return;
}
final Management management = commandService.getManagement();
if (Settings.emailRegistration && !Settings.getmailAccount.isEmpty()) {
if (Settings.doubleEmailCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) {
commandService.send(player, MessageKey.USAGE_REGISTER);
return;
}
final String email = arguments.get(0);
if (!Utils.isEmailCorrect(email, commandService.getSettings())) {
commandService.send(player, MessageKey.INVALID_EMAIL);
return;
}
final String thePass = RandomString.generate(Settings.getRecoveryPassLength);
management.performRegister(player, thePass, email);
return;
if (commandService.getProperty(USE_EMAIL_REGISTRATION)) {
handleEmailRegistration(player, arguments, commandService);
} else {
handlePasswordRegistration(player, arguments, commandService);
}
if (arguments.size() > 1 && Settings.enablePasswordConfirmation && !arguments.get(0).equals(arguments.get(1))) {
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return;
}
management.performRegister(player, arguments.get(0), "");
}
@Override
public String getAlternativeCommand() {
protected String getAlternativeCommand() {
return "/authme register <playername> <password>";
}
private void handlePasswordRegistration(Player player, List<String> arguments, CommandService commandService) {
if (commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
} else {
commandService.getManagement().performRegister(player, arguments.get(0), "");
}
}
private void handleEmailRegistration(Player player, List<String> arguments, CommandService commandService) {
if (commandService.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
player.sendMessage("Cannot register: no email address is set for the server. "
+ "Please contact an administrator");
ConsoleLogger.showError("Cannot register player '" + player.getName() + "': no email is set "
+ "to send emails from. Please add one in your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
return;
}
final String email = arguments.get(0);
if (!commandService.validateEmail(email)) {
commandService.send(player, MessageKey.INVALID_EMAIL);
} else if (commandService.getProperty(ENABLE_CONFIRM_EMAIL) && !email.equals(arguments.get(1))) {
commandService.send(player, MessageKey.USAGE_REGISTER);
} else {
String thePass = RandomString.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
commandService.getManagement().performRegister(player, thePass, email);
}
}
/**
* Return whether the password or email has to be confirmed.
*
* @param commandService The command service
* @return True if the confirmation is needed, false otherwise
*/
private boolean isConfirmationRequired(CommandService commandService) {
return commandService.getProperty(USE_EMAIL_REGISTRATION)
? commandService.getProperty(ENABLE_CONFIRM_EMAIL)
: commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
}
}

View File

@ -4,7 +4,6 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
@ -25,22 +24,23 @@ public class RakamakConverter implements Converter {
private final AuthMe instance;
private final DataSource database;
private final CommandSender sender;
private final File pluginFolder;
public RakamakConverter(AuthMe instance, CommandSender sender) {
this.instance = instance;
this.database = instance.getDataSource();
this.sender = sender;
pluginFolder = instance.getDataFolder();
}
@Override
// TODO ljacqu 20151229: Restructure this into smaller portions
public void run() {
HashAlgorithm hash = Settings.getPasswordHash;
boolean useIP = Settings.rakamakUseIp;
String fileName = Settings.rakamakUsers;
String ipFileName = Settings.rakamakUsersIp;
File source = new File(Settings.PLUGIN_FOLDER, fileName);
File ipfiles = new File(Settings.PLUGIN_FOLDER, ipFileName);
File source = new File(pluginFolder, fileName);
File ipfiles = new File(pluginFolder, ipFileName);
HashMap<String, String> playerIP = new HashMap<>();
HashMap<String, HashedPassword> playerPSW = new HashMap<>();
try {
@ -64,7 +64,7 @@ public class RakamakConverter implements Converter {
while ((line = users.readLine()) != null) {
if (line.contains("=")) {
String[] arguments = line.split("=");
HashedPassword hashedPassword = passwordSecurity.computeHash(hash, arguments[1], arguments[0]);
HashedPassword hashedPassword = passwordSecurity.computeHash(arguments[1], arguments[0]);
playerPSW.put(arguments[0], hashedPassword);
}

View File

@ -250,9 +250,4 @@ public class CacheDataSource implements DataSource {
public List<PlayerAuth> getLoggedPlayers() {
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
}
@Override
public boolean isEmailStored(String email) {
return source.isEmailStored(email);
}
}

View File

@ -122,70 +122,84 @@ public interface DataSource {
void close();
/**
* Method purgeBanned.
* Purge all given players, i.e. delete all players whose name is in the list.
*
* @param banned List of String
* @param banned the list of players to delete
*/
void purgeBanned(List<String> banned);
/**
* Method getType.
* Return the data source type.
*
* @return DataSourceType
* @return the data source type
*/
DataSourceType getType();
/**
* Method isLogged.
* Query the datasource whether the player is logged in or not.
*
* @param user String
*
* @return boolean
* @param user The name of the player to verify
* @return True if logged in, false otherwise
*/
boolean isLogged(String user);
/**
* Method setLogged.
* Set a player as logged in.
*
* @param user String
* @param user The name of the player to change
*/
void setLogged(String user);
/**
* Method setUnlogged.
* Set a player as unlogged (not logged in).
*
* @param user String
* @param user The name of the player to change
*/
void setUnlogged(String user);
/**
* Set all players who are marked as logged in as NOT logged in.
*/
void purgeLogged();
/**
* Method getAccountsRegistered.
* Return all players which are logged in.
*
* @return int
*/
int getAccountsRegistered();
boolean updateRealName(String user, String realName);
boolean updateIp(String user, String ip);
/**
* Method getAllAuths.
*
* @return List of PlayerAuth
*/
List<PlayerAuth> getAllAuths();
/**
* Method getLoggedPlayers.
*
* @return List of PlayerAuth
* @return All logged in players
*/
List<PlayerAuth> getLoggedPlayers();
boolean isEmailStored(String email);
/**
* Return the number of registered accounts.
*
* @return Total number of accounts
*/
int getAccountsRegistered();
/**
* Update a player's real name (capitalization).
*
* @param user The name of the user (lowercase)
* @param realName The real name of the user (proper casing)
* @return True upon success, false upon failure
*/
boolean updateRealName(String user, String realName);
/**
* Update a player's IP address.
*
* @param user The name of the user (lowercase)
* @param ip The IP address to save
* @return True upon success, false upon failure
*/
boolean updateIp(String user, String ip);
/**
* Return all players of the database.
*
* @return List of all players
*/
List<PlayerAuth> getAllAuths();
/**
* Reload the data source.

View File

@ -521,11 +521,6 @@ public class FlatFile implements DataSource {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public boolean isEmailStored(String email) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
private static PlayerAuth buildAuthFromArray(String[] args) {
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {

View File

@ -274,20 +274,20 @@ public class MySQL implements DataSource {
@Override
public HashedPassword getPassword(String user) {
String sql = "SELECT " + col.PASSWORD + "," + col.SALT + " FROM " + tableName
+ " WHERE " + col.NAME + "=?;";
ResultSet rs = null;
boolean useSalt = !col.SALT.isEmpty();
String sql = "SELECT " + col.PASSWORD
+ (useSalt ? ", " + col.SALT : "")
+ " FROM " + tableName + " WHERE " + col.NAME + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, user.toLowerCase());
rs = pst.executeQuery();
if (rs.next()) {
return new HashedPassword(rs.getString(col.PASSWORD),
!col.SALT.isEmpty() ? rs.getString(col.SALT) : null);
try (ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return new HashedPassword(rs.getString(col.PASSWORD),
useSalt ? rs.getString(col.SALT) : null);
}
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(rs);
}
return null;
}
@ -429,7 +429,7 @@ public class MySQL implements DataSource {
rs = pst.executeQuery();
if (rs.next()) {
int id = rs.getInt(col.ID);
sql = "INSERT INTO " + wordpressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?);";
sql = "INSERT INTO " + wordpressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?)";
pst2 = con.prepareStatement(sql);
// First Name
pst2.setInt(1, id);
@ -478,12 +478,12 @@ public class MySQL implements DataSource {
pst2.addBatch();
// wp_capabilities
pst2.setInt(1, id);
pst2.setString(2, "wp_capabilities");
pst2.setString(2, wordpressPrefix + "capabilities");
pst2.setString(3, "a:1:{s:10:\"subscriber\";b:1;}");
pst2.addBatch();
// wp_user_level
pst2.setInt(1, id);
pst2.setString(2, "wp_user_level");
pst2.setString(2, wordpressPrefix + "user_level");
pst2.setString(3, "0");
pst2.addBatch();
// default_password_nag
@ -908,20 +908,6 @@ public class MySQL implements DataSource {
return auths;
}
@Override
public synchronized boolean isEmailStored(String email) {
String sql = "SELECT 1 FROM " + tableName + " WHERE UPPER(" + col.EMAIL + ") = UPPER(?)";
try (Connection con = ds.getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, email);
try (ResultSet rs = pst.executeQuery()) {
return rs.next();
}
} catch (SQLException e) {
logSqlException(e);
}
return false;
}
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
String salt = col.SALT.isEmpty() ? null : row.getString(col.SALT);
int group = col.GROUP.isEmpty() ? -1 : row.getInt(col.GROUP);

View File

@ -154,22 +154,20 @@ public class SQLite implements DataSource {
@Override
public HashedPassword getPassword(String user) {
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = con.prepareStatement("SELECT " + col.PASSWORD + "," + col.SALT
+ " FROM " + tableName + " WHERE " + col.NAME + "=?");
boolean useSalt = !col.SALT.isEmpty();
String sql = "SELECT " + col.PASSWORD
+ (useSalt ? ", " + col.SALT : "")
+ " FROM " + tableName + " WHERE " + col.NAME + "=?";
try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, user);
rs = pst.executeQuery();
if (rs.next()) {
return new HashedPassword(rs.getString(col.PASSWORD),
!col.SALT.isEmpty() ? rs.getString(col.SALT) : null);
try (ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return new HashedPassword(rs.getString(col.PASSWORD),
useSalt ? rs.getString(col.SALT) : null);
}
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(rs);
close(pst);
}
return null;
}
@ -580,22 +578,6 @@ public class SQLite implements DataSource {
return auths;
}
@Override
public synchronized boolean isEmailStored(String email) {
String sql = "SELECT 1 FROM " + tableName + " WHERE " + col.EMAIL + " = ? COLLATE NOCASE;";
ResultSet rs = null;
try (PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1, email);
rs = ps.executeQuery();
return rs.next();
} catch (SQLException e) {
logSqlException(e);
} finally {
close(rs);
}
return false;
}
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null;

View File

@ -7,7 +7,6 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.security.crypts.HashedPassword;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
@ -17,17 +16,14 @@ import org.bukkit.plugin.messaging.PluginMessageListener;
public class BungeeCordMessage implements PluginMessageListener {
private final AuthMe plugin;
private final IpAddressManager ipAddressManager;
/**
* Constructor for BungeeCordMessage.
*
* @param plugin The plugin instance
* @param ipAddressManager The IP address manager
*/
public BungeeCordMessage(AuthMe plugin, IpAddressManager ipAddressManager) {
public BungeeCordMessage(AuthMe plugin) {
this.plugin = plugin;
this.ipAddressManager = ipAddressManager;
}
@Override
@ -37,11 +33,6 @@ public class BungeeCordMessage implements PluginMessageListener {
}
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String subChannel = in.readUTF();
if ("IP".equals(subChannel)) { // We need only the IP channel
String ip = in.readUTF();
// Put the IP (only the ip not the port) in the hashMap
ipAddressManager.addCache(player.getName(), ip);
}
if ("AuthMe".equalsIgnoreCase(subChannel)) {
String str = in.readUTF();
final String[] args = str.split(";");

View File

@ -1,17 +1,19 @@
package fr.xephi.authme.hooks;
import com.earth2me.essentials.Essentials;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.ConsoleLogger;
import net.minelink.ctplus.CombatTagPlus;
import java.io.File;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import java.io.File;
import com.earth2me.essentials.Essentials;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.ConsoleLogger;
import net.minelink.ctplus.CombatTagPlus;
/**
* Hooks into third-party plugins and allows to perform actions on them.

View File

@ -33,7 +33,7 @@ public class AuthMeEntityListener implements Listener {
}
}
// TODO #360: npc status can be used to bypass security!!!
// Note #360: npc status can be used to bypass security!!!
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onEntityDamage(EntityDamageEvent event) {
if (shouldCancelEvent(event)) {

View File

@ -22,7 +22,6 @@ import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.MethodUtils;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
@ -38,6 +37,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.apache.commons.lang.reflect.MethodUtils;
public class AuthMeInventoryPacketAdapter extends PacketAdapter {
private static final int PLAYER_INVENTORY = 0;
@ -127,9 +128,11 @@ public class AuthMeInventoryPacketAdapter extends PacketAdapter {
PacketContainer inventoryPacket = protocolManager.createPacket(PacketType.Play.Server.WINDOW_ITEMS);
inventoryPacket.getIntegers().write(0, PLAYER_INVENTORY);
int inventorySize = CRAFTING_SIZE + ARMOR_SIZE + MAIN_SIZE + HOTBAR_SIZE;
ItemStack[] blankInventory = new ItemStack[inventorySize];
Arrays.fill(blankInventory, new ItemStack(Material.AIR));
inventoryPacket.getItemArrayModifier().write(0, blankInventory);
try {
protocolManager.sendServerPacket(player, inventoryPacket, false);
} catch (InvocationTargetException invocationExc) {

View File

@ -3,6 +3,7 @@ package fr.xephi.authme.listener;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.AntiBot.AntiBotStatus;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
@ -15,9 +16,15 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@ -50,56 +57,65 @@ import org.bukkit.event.player.PlayerShearEntityEvent;
import java.util.concurrent.ConcurrentHashMap;
import static fr.xephi.authme.listener.ListenerService.shouldCancelEvent;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT;
/**
* Listener class for player's events
* Listener class for player events.
*/
public class AuthMePlayerListener implements Listener {
public static final ConcurrentHashMap<String, String> joinMessage = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<String, Boolean> causeByAuthMe = new ConcurrentHashMap<>();
private final AuthMe plugin;
private final NewSetting settings;
private final Messages m;
private final DataSource dataSource;
private final AntiBot antiBot;
private final Management management;
private final BukkitService bukkitService;
private final ValidationService validationService;
public AuthMePlayerListener(AuthMe plugin, Messages messages, DataSource dataSource, AntiBot antiBot,
Management management) {
public AuthMePlayerListener(AuthMe plugin, NewSetting settings, Messages messages, DataSource dataSource,
AntiBot antiBot, Management management, BukkitService bukkitService,
ValidationService validationService) {
this.plugin = plugin;
this.settings = settings;
this.m = messages;
this.dataSource = dataSource;
this.antiBot = antiBot;
this.management = management;
this.bukkitService = bukkitService;
this.validationService = validationService;
}
private void handleChat(AsyncPlayerChatEvent event) {
if (Settings.isChatAllowed) {
if (settings.getProperty(RestrictionSettings.ALLOW_CHAT)) {
return;
}
final Player player = event.getPlayer();
if (Utils.checkAuth(player)) {
for (Player p : Utils.getOnlinePlayers()) {
if (shouldCancelEvent(player)) {
event.setCancelled(true);
sendLoginOrRegisterMessage(player);
} else if (settings.getProperty(RestrictionSettings.HIDE_CHAT)) {
for (Player p : bukkitService.getOnlinePlayers()) {
if (!PlayerCache.getInstance().isAuthenticated(p.getName())) {
event.getRecipients().remove(p); // TODO: it should be configurable
event.getRecipients().remove(p);
}
}
return;
}
event.setCancelled(true);
sendLoginOrRegisterMessage(player);
}
private void sendLoginOrRegisterMessage(final Player player) {
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
bukkitService.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
if (dataSource.isAuthAvailable(player.getName().toLowerCase())) {
m.send(player, MessageKey.LOGIN_MESSAGE);
} else {
if (Settings.emailRegistration) {
if (settings.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)) {
m.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
} else {
m.send(player, MessageKey.REGISTER_MESSAGE);
@ -112,13 +128,14 @@ public class AuthMePlayerListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
String cmd = event.getMessage().split(" ")[0].toLowerCase();
if (Settings.useEssentialsMotd && cmd.equals("/motd")) {
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && "/motd".equals(cmd)) {
return;
}
if (!Settings.isForcedRegistrationEnabled && Settings.allowAllCommandsIfRegIsOptional) {
if (!settings.getProperty(RegistrationSettings.FORCE)
&& settings.getProperty(ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL)) {
return;
}
if (Settings.allowCommands.contains(cmd)) {
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
return;
}
if (Utils.checkAuth(event.getPlayer())) {
@ -155,13 +172,17 @@ public class AuthMePlayerListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onPlayerMove(PlayerMoveEvent event) {
if (Settings.isMovementAllowed && Settings.getMovementRadius <= 0) {
if (settings.getProperty(ALLOW_UNAUTHED_MOVEMENT) && settings.getProperty(ALLOWED_MOVEMENT_RADIUS) <= 0) {
return;
}
/*
* Limit player X and Z movements to 1 block
* Deny player Y+ movements (allows falling)
*/
if (event.getFrom().getBlockX() == event.getTo().getBlockX()
&& event.getFrom().getBlockY() == event.getTo().getBlockY()
&& event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
&& event.getFrom().getBlockZ() == event.getTo().getBlockZ()
&& event.getFrom().getY() - event.getTo().getY() >= 0) {
return;
}
@ -170,16 +191,17 @@ public class AuthMePlayerListener implements Listener {
return;
}
if (!Settings.isMovementAllowed) {
if (!settings.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)) {
event.setTo(event.getFrom());
if (Settings.isRemoveSpeedEnabled) {
// sgdc3 TODO: remove this, maybe we should set the effect every x ticks, idk!
if (settings.getProperty(RestrictionSettings.REMOVE_SPEED)) {
player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f);
}
return;
}
if (Settings.noTeleport) {
if (settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
return;
}
@ -189,7 +211,7 @@ public class AuthMePlayerListener implements Listener {
player.teleport(spawn);
return;
}
if (spawn.distance(player.getLocation()) > Settings.getMovementRadius) {
if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
player.teleport(spawn);
}
}
@ -202,11 +224,11 @@ public class AuthMePlayerListener implements Listener {
return;
}
if (Settings.removeJoinMessage) {
if (settings.getProperty(RegistrationSettings.REMOVE_JOIN_MESSAGE)) {
event.setJoinMessage(null);
return;
}
if (!Settings.delayJoinMessage) {
if (!settings.getProperty(RegistrationSettings.DELAY_JOIN_MESSAGE)) {
return;
}
@ -214,11 +236,10 @@ public class AuthMePlayerListener implements Listener {
String joinMsg = event.getJoinMessage();
// Remove the join message while the player isn't logging in
if (joinMsg == null) {
return;
if (joinMsg != null) {
event.setJoinMessage(null);
joinMessage.put(name, joinMsg);
}
event.setJoinMessage(null);
joinMessage.put(name, joinMsg);
}
@EventHandler(priority = EventPriority.LOW)
@ -228,14 +249,14 @@ public class AuthMePlayerListener implements Listener {
return;
}
if (Settings.isForceSurvivalModeEnabled
if (settings.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
&& !player.hasPermission(PlayerStatePermission.BYPASS_FORCE_SURVIVAL.getNode())) {
player.setGameMode(GameMode.SURVIVAL);
}
// Shedule login task so works after the prelogin
// (Fix found by Koolaid5000)
Bukkit.getScheduler().runTask(plugin, new Runnable() {
bukkitService.runTask(new Runnable() {
@Override
public void run() {
management.performJoin(player);
@ -246,40 +267,32 @@ public class AuthMePlayerListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onPreLogin(AsyncPlayerPreLoginEvent event) {
PlayerAuth auth = dataSource.getAuth(event.getName());
if (Settings.preventOtherCase && auth != null && auth.getRealName() != null) {
if (settings.getProperty(RegistrationSettings.PREVENT_OTHER_CASE) && auth != null && auth.getRealName() != null) {
String realName = auth.getRealName();
if (!realName.isEmpty() && !realName.equals("Player") && !realName.equals(event.getName())) {
if (!realName.isEmpty() && !"Player".equals(realName) && !realName.equals(event.getName())) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.INVALID_NAME_CASE, realName, event.getName()));
return;
}
if (realName.isEmpty() || realName.equals("Player")) {
if (realName.isEmpty() || "Player".equals(realName)) {
dataSource.updateRealName(event.getName().toLowerCase(), event.getName());
}
}
if (auth == null) {
if (!Settings.countriesBlacklist.isEmpty() || !Settings.countries.isEmpty()) {
String playerIP = event.getAddress().getHostAddress();
String countryCode = GeoLiteAPI.getCountryCode(playerIP);
if (Settings.countriesBlacklist.contains(countryCode)) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
return;
}
if (Settings.enableProtection && !Settings.countries.contains(countryCode)) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
return;
}
if (auth == null && settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)) {
String playerIp = event.getAddress().getHostAddress();
if (!validationService.isCountryAdmitted(playerIp)) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
return;
}
}
final String name = event.getName().toLowerCase();
final Player player = Utils.getPlayer(name);
final Player player = bukkitService.getPlayerExact(name);
// Check if forceSingleSession is set to true, so kick player that has
// joined with same nick of online player
if (player != null && Settings.isForceSingleSessionEnabled) {
if (player != null && settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.USERNAME_ALREADY_ONLINE_ERROR));
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
@ -302,11 +315,11 @@ public class AuthMePlayerListener implements Listener {
if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL) {
if (permsMan.hasPermission(player, PlayerStatePermission.IS_VIP)) {
int playersOnline = Utils.getOnlinePlayers().size();
int playersOnline = bukkitService.getOnlinePlayers().size();
if (playersOnline > plugin.getServer().getMaxPlayers()) {
event.allow();
} else {
Player pl = plugin.generateKickPlayer(Utils.getOnlinePlayers());
Player pl = plugin.generateKickPlayer(bukkitService.getOnlinePlayers());
if (pl != null) {
pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
event.allow();
@ -330,16 +343,16 @@ public class AuthMePlayerListener implements Listener {
final String name = player.getName().toLowerCase();
boolean isAuthAvailable = dataSource.isAuthAvailable(name);
if (Settings.isKickNonRegisteredEnabled && !isAuthAvailable) {
if (Settings.antiBotInAction) {
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_ANTIBOT));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
return;
} else {
event.setKickMessage(m.retrieveSingle(MessageKey.MUST_REGISTER_MESSAGE));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
return;
}
if (antiBot.getAntiBotStatus() == AntiBotStatus.ACTIVE && !isAuthAvailable) {
event.setKickMessage(m.retrieveSingle(MessageKey.KICK_ANTIBOT));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
return;
}
if (settings.getProperty(RestrictionSettings.KICK_NON_REGISTERED) && !isAuthAvailable) {
event.setKickMessage(m.retrieveSingle(MessageKey.MUST_REGISTER_MESSAGE));
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
return;
}
if (name.length() > Settings.getMaxNickLength || name.length() < Settings.getMinNickLength) {
@ -356,7 +369,7 @@ public class AuthMePlayerListener implements Listener {
antiBot.checkAntiBot(player);
if (Settings.bungee) {
if (settings.getProperty(HooksSettings.BUNGEECORD)) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("IP");
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
@ -371,7 +384,7 @@ public class AuthMePlayerListener implements Listener {
return;
}
if (Settings.removeLeaveMessage) {
if (settings.getProperty(RegistrationSettings.REMOVE_LEAVE_MESSAGE)) {
event.setQuitMessage(null);
}
@ -386,8 +399,8 @@ public class AuthMePlayerListener implements Listener {
return;
}
if ((!Settings.isForceSingleSessionEnabled)
&& (event.getReason().equals(m.retrieveSingle(MessageKey.USERNAME_ALREADY_ONLINE_ERROR)))) {
if (!settings.getProperty(RestrictionSettings.FORCE_SINGLE_SESSION)
&& event.getReason().equals(m.retrieveSingle(MessageKey.USERNAME_ALREADY_ONLINE_ERROR))) {
event.setCancelled(true);
return;
}

View File

@ -0,0 +1,26 @@
package fr.xephi.authme.listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.spigotmc.event.player.PlayerSpawnLocationEvent;
import fr.xephi.authme.AuthMe;
/**
* Listener of player events for events introduced in Minecraft 1.9.
*/
public class AuthMePlayerListener19 implements Listener {
private final AuthMe plugin;
public AuthMePlayerListener19(AuthMe plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerSpawn(PlayerSpawnLocationEvent event) {
event.setSpawnLocation(plugin.getSpawnLocation(event.getPlayer()));
}
}

View File

@ -5,9 +5,10 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@ -21,25 +22,26 @@ public class AuthMeServerListener implements Listener {
private final AuthMe plugin;
private final Messages messages;
private final NewSetting settings;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
private final ValidationService validationService;
public AuthMeServerListener(AuthMe plugin, Messages messages, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
public AuthMeServerListener(AuthMe plugin, Messages messages, NewSetting settings, PluginHooks pluginHooks,
SpawnLoader spawnLoader, ValidationService validationService) {
this.plugin = plugin;
this.messages = messages;
this.settings = settings;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
this.validationService = validationService;
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onServerPing(ServerListPingEvent event) {
if (!Settings.countriesBlacklist.isEmpty() || !Settings.countries.isEmpty()){
String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress());
if( Settings.countriesBlacklist.contains(countryCode)) {
event.setMotd(messages.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
return;
}
if (Settings.enableProtection && !Settings.countries.contains(countryCode)) {
if (settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)) {
String playerIp = event.getAddress().getHostAddress();
if (!validationService.isCountryAdmitted(playerIp)) {
event.setMotd(messages.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
}
}
@ -52,6 +54,9 @@ public class AuthMeServerListener implements Listener {
return;
}
// Call the onPluginDisable method in the permissions manager
plugin.getPermissionsManager().onPluginDisable(event);
final String pluginName = event.getPlugin().getName();
if ("Essentials".equalsIgnoreCase(pluginName)) {
pluginHooks.unhookEssentials();
@ -82,6 +87,9 @@ public class AuthMeServerListener implements Listener {
return;
}
// Call the onPluginEnable method in the permissions manager
plugin.getPermissionsManager().onPluginEnable(event);
final String pluginName = event.getPlugin().getName();
if ("Essentials".equalsIgnoreCase(pluginName)) {
pluginHooks.tryHookToEssentials();

View File

@ -6,6 +6,7 @@ import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.FieldAccessException;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;

View File

@ -2,40 +2,96 @@ package fr.xephi.authme.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.logging.Level;
public class AuthMeTablistPacketAdapter extends PacketAdapter {
public AuthMeTablistPacketAdapter(AuthMe plugin) {
private final BukkitService bukkitService;
public AuthMeTablistPacketAdapter(AuthMe plugin, BukkitService bukkitService) {
super(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.PLAYER_INFO);
this.bukkitService = bukkitService;
}
@Override
public void onPacketSending(PacketEvent event) {
if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) {
//this hides the tablist for the new joining players. Already playing users will see the new player
try {
if (!PlayerCache.getInstance().isAuthenticated(event.getPlayer().getName().toLowerCase())) {
event.setCancelled(true);
}
} catch (FieldAccessException e) {
ConsoleLogger.showError("Couldn't access field.");
ConsoleLogger.logException("Couldn't access field", e);
}
}
}
// TODO: fix this in 1.9
public void sendTablist(Player receiver) {
WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(receiver);
ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
NativeGameMode gamemode = NativeGameMode.fromBukkit(receiver.getGameMode());
WrappedChatComponent displayName = WrappedChatComponent.fromText(receiver.getDisplayName());
PlayerInfoData playerInfoData = new PlayerInfoData(gameProfile, 0, gamemode, displayName);
//add info containing the skin data
PacketContainer addInfo = protocolManager.createPacket(PacketType.Play.Server.PLAYER_INFO);
addInfo.getPlayerInfoAction().write(0, PlayerInfoAction.ADD_PLAYER);
addInfo.getPlayerInfoDataLists().write(0, Arrays.asList(playerInfoData));
try {
//adds the skin
protocolManager.sendServerPacket(receiver, addInfo);
} catch (InvocationTargetException ex) {
plugin.getLogger().log(Level.SEVERE, "Exception sending instant skin change packet", ex);
}
//triggers an update for others player to see them
for (Player onlinePlayer : bukkitService.getOnlinePlayers()) {
if (onlinePlayer.equals(receiver) || !receiver.canSee(onlinePlayer)) {
continue;
}
//removes the entity and display them
receiver.hidePlayer(onlinePlayer);
receiver.showPlayer(onlinePlayer);
}
}
public void register() {
ConsoleLogger.showError("The hideTablistBeforeLogin feature is temporarily disabled due to issues with 1.9 clients.");
//ProtocolLibrary.getProtocolManager().addPacketListener(this);
if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.BOUNTIFUL_UPDATE)) {
ProtocolLibrary.getProtocolManager().addPacketListener(this);
} else {
ConsoleLogger.info("The hideTablist feature is not compatible with your minecraft version");
ConsoleLogger.info("It requires 1.8+. Disabling the hideTablist feature...");
}
}
public void unregister() {
//ProtocolLibrary.getProtocolManager().removePacketListener(this);
ProtocolLibrary.getProtocolManager().removePacketListener(this);
}
}

View File

@ -1,38 +0,0 @@
package fr.xephi.authme.modules;
/**
*/
public abstract class Module {
/**
* Method getName.
*
* @return String
*/
public abstract String getName();
/**
* Method getType.
*
* @return ModuleType
*/
public abstract ModuleType getType();
public void load() {
}
public void unload() {
}
/**
*/
enum ModuleType {
MANAGER,
MYSQL,
REDIS,
ACTIONS,
CONVERTERS,
EMAILS,
CUSTOM
}
}

View File

@ -1,184 +0,0 @@
package fr.xephi.authme.modules;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.Settings;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
*/
public class ModuleManager {
private final List<Module> modules = new ArrayList<>();
/**
* Constructor for ModuleManager.
*
* @param plugin AuthMe
*/
public ModuleManager(AuthMe plugin) {
}
/**
* Method isModuleEnabled.
*
* @param name String
*
* @return boolean
*/
public boolean isModuleEnabled(String name) {
for (Module m : modules) {
if (m.getName().equalsIgnoreCase(name))
return true;
}
return false;
}
/**
* Method isModuleEnabled.
*
* @param type Module.ModuleType
*
* @return boolean
*/
public boolean isModuleEnabled(Module.ModuleType type) {
for (Module m : modules) {
if (m.getType() == type)
return true;
}
return false;
}
/**
* Method getModule.
*
* @param name String
*
* @return Module
*/
public Module getModule(String name) {
for (Module m : modules) {
if (m.getName().equalsIgnoreCase(name))
return m;
}
return null;
}
/**
* Method getModule.
*
* @param type Module.ModuleType
*
* @return Module
*/
public Module getModule(Module.ModuleType type) {
for (Module m : modules) {
if (m.getType() == type)
return m;
}
return null;
}
/**
* Method loadModules.
*
* @return int
*/
public int loadModules() {
File dir = Settings.MODULE_FOLDER;
int count = 0;
if (!dir.isDirectory()) {
dir.mkdirs();
return count;
}
File[] files = dir.listFiles();
if (files == null) {
return count;
}
for (File pathToJar : files) {
JarFile jarFile = null;
URLClassLoader cl = null;
try {
jarFile = new JarFile(pathToJar);
URL[] urls = {new URL("jar:file:" + pathToJar.getAbsolutePath() + "!/")};
cl = URLClassLoader.newInstance(urls);
Enumeration<?> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
if (je.isDirectory() || !je.getName().endsWith("Main.class")) {
continue;
}
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
Class<?> c = cl.loadClass(className);
if (!Module.class.isAssignableFrom(c)) {
continue;
}
Module mod = (Module) c.newInstance();
mod.load();
modules.add(mod);
count++;
break;
}
} catch (Exception ex) {
ConsoleLogger.logException("Cannot load " + pathToJar.getName() + " jar file!", ex);
} finally {
try {
if (jarFile != null) {
jarFile.close();
}
if (cl != null) {
cl.close();
}
} catch (IOException ignored) {
}
}
}
return count;
}
public void reloadModules() {
unloadModules();
loadModules();
}
/**
* Method unloadModule.
*
* @param name String
*/
public void unloadModule(String name) {
Iterator<Module> it = modules.iterator();
while (it.hasNext()) {
Module m = it.next();
if (m.getName().equalsIgnoreCase(name)) {
m.unload();
it.remove();
return;
}
}
}
public void unloadModules() {
Iterator<Module> it = modules.iterator();
while (it.hasNext()) {
it.next().unload();
it.remove();
}
}
}

View File

@ -76,6 +76,9 @@ public class Messages {
+ "Please verify your config file at '" + fileName + "'");
return formatMessage(getDefault(code));
}
if(message.isEmpty()) {
return new String[0];
}
return formatMessage(message);
}

View File

@ -1,11 +1,10 @@
package fr.xephi.authme.permission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import de.bananaco.bpermissions.api.ApiLayer;
import de.bananaco.bpermissions.api.CalculableType;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.util.CollectionUtils;
import net.milkbowl.vault.permission.Permission;
import org.anjocaido.groupmanager.GroupManager;
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
import org.bukkit.Bukkit;
@ -18,15 +17,15 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
import de.bananaco.bpermissions.api.ApiLayer;
import de.bananaco.bpermissions.api.CalculableType;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.util.CollectionUtils;
import net.milkbowl.vault.permission.Permission;
import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* <p>
* PermissionsManager.
@ -49,18 +48,10 @@ public class PermissionsManager implements PermissionsService {
* Server instance.
*/
private final Server server;
/**
* Plugin instance.
*/
private final Plugin plugin;
/**
* Logger instance.
*/
private Logger log;
/**
* The permissions manager Bukkit listener instance.
*/
private PermissionsManagerBukkitListener bukkitListener;
/**
* Type of permissions system that is currently used.
* Null if no permissions system is hooked and/or used.
@ -79,28 +70,11 @@ public class PermissionsManager implements PermissionsService {
* Constructor.
*
* @param server Server instance
* @param plugin Plugin instance
* @param log Logger
*/
public PermissionsManager(Server server, Plugin plugin, Logger log) {
public PermissionsManager(Server server, Logger log) {
this.server = server;
this.plugin = plugin;
this.log = log;
// Create and register the Bukkit listener on the server if it's valid
if(this.server != null) {
// Create the Bukkit listener
this.bukkitListener = new PermissionsManagerBukkitListener(this);
// Get the plugin manager instance
PluginManager pluginManager = this.server.getPluginManager();
// Register the Bukkit listener
pluginManager.registerEvents(this.bukkitListener, this.plugin);
// Show a status message.
//this.log.info("Started permission plugins state listener!");
}
}
/**
@ -282,15 +256,6 @@ public class PermissionsManager implements PermissionsService {
}
}
/**
* Get the permissions manager Bukkit listener instance.
*
* @return Listener instance.
*/
public PermissionsManagerBukkitListener getListener() {
return this.bukkitListener;
}
/**
* Check if the command sender has permission for the given permissions node. If no permissions system is used or
* if the sender is not a player (e.g. console user), the player has to be OP in order to have the permission.

View File

@ -1,85 +0,0 @@
package fr.xephi.authme.permission;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
public class PermissionsManagerBukkitListener implements Listener {
/**
* The permissions manager instance.
*/
private PermissionsManager permissionsManager;
/**
* Whether the listener is enabled or not.
*/
private boolean enabled = true;
/**
* Constructor.\
*
* @param permissionsManager Permissions manager instance.
*/
public PermissionsManagerBukkitListener(PermissionsManager permissionsManager) {
this.permissionsManager = permissionsManager;
}
/**
* Check whether the listener is enabled.
*
* @return True if the listener is enabled.
*/
public boolean isEnabled() {
return this.enabled;
}
/**
* Set whether the listener is enabled.
* Disabling the listener will stop the event handling until it's enabled again.
*
* @param enabled True if enabled, false if disabled.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* Called when a plugin is enabled.
*
* @param event Event reference.
*/
@EventHandler
public void onPluginEnable(PluginEnableEvent event) {
// Make sure the listener is enabled
if(!isEnabled())
return;
// Make sure the permissions manager is set
if(this.permissionsManager == null)
return;
// Call the onPluginEnable method in the permissions manager
permissionsManager.onPluginEnable(event);
}
/**
* Called when a plugin is disabled.
*
* @param event Event reference.
*/
@EventHandler
public void onPluginDisable(PluginDisableEvent event) {
// Make sure the listener is enabled
if(!isEnabled())
return;
// Make sure the permissions manager is set
if(this.permissionsManager == null)
return;
// Call the onPluginDisable method in the permissions manager
permissionsManager.onPluginDisable(event);
}
}

View File

@ -41,7 +41,7 @@ public class Management {
}
public void performRegister(final Player player, final String password, final String email) {
runTask(new AsyncRegister(player, password, email, plugin, dataSource, processService));
runTask(new AsyncRegister(player, password, email, plugin, dataSource, playerCache, processService));
}
public void performUnregister(final Player player, final String password, final boolean force) {

View File

@ -1,7 +1,6 @@
package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
@ -11,10 +10,15 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitTask;
import java.util.Collection;
/**
* Service for asynchronous and synchronous processes.
*/
@ -24,22 +28,24 @@ public class ProcessService {
private final Messages messages;
private final AuthMe authMe;
private final DataSource dataSource;
private final IpAddressManager ipAddressManager;
private final PasswordSecurity passwordSecurity;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
private final ValidationService validationService;
private final BukkitService bukkitService;
public ProcessService(NewSetting settings, Messages messages, AuthMe authMe, DataSource dataSource,
IpAddressManager ipAddressManager, PasswordSecurity passwordSecurity, PluginHooks pluginHooks,
SpawnLoader spawnLoader) {
PasswordSecurity passwordSecurity, PluginHooks pluginHooks, SpawnLoader spawnLoader,
ValidationService validationService, BukkitService bukkitService) {
this.settings = settings;
this.messages = messages;
this.authMe = authMe;
this.dataSource = dataSource;
this.ipAddressManager = ipAddressManager;
this.passwordSecurity = passwordSecurity;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
this.validationService = validationService;
this.bukkitService = bukkitService;
}
/**
@ -152,15 +158,6 @@ public class ProcessService {
return authMe;
}
/**
* Return the IP address manager.
*
* @return the ip address manager
*/
public IpAddressManager getIpAddressManager() {
return ipAddressManager;
}
/**
* Compute the hash for the given password.
*
@ -199,4 +196,31 @@ public class ProcessService {
return dataSource;
}
/**
* Verifies whether a password is valid according to the plugin settings.
*
* @param password the password to verify
* @param username the username the password is associated with
* @return message key with the password error, or {@code null} if password is valid
*/
public MessageKey validatePassword(String password, String username) {
return validationService.validatePassword(password, username);
}
public boolean validateEmail(String email) {
return validationService.validateEmail(email);
}
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
return validationService.isEmailFreeForRegistration(email, sender);
}
public Collection<? extends Player> getOnlinePlayers() {
return bukkitService.getOnlinePlayers();
}
public BukkitService getBukkitService() {
return bukkitService;
}
}

View File

@ -8,7 +8,6 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
/**
@ -41,9 +40,9 @@ public class AsyncAddEmail implements Process {
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
} else if (!Utils.isEmailCorrect(email, service.getSettings())) {
} else if (!service.validateEmail(email)) {
service.send(player, MessageKey.INVALID_EMAIL);
} else if (dataSource.isEmailStored(email)) {
} else if (!service.isEmailFreeForRegistration(email, player)) {
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else {
auth.setEmail(email);

View File

@ -7,7 +7,6 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
/**
@ -41,11 +40,11 @@ public class AsyncChangeEmail implements Process {
if (currentEmail == null) {
service.send(player, MessageKey.USAGE_ADD_EMAIL);
} else if (newEmail == null || !Utils.isEmailCorrect(newEmail, service.getSettings())) {
} else if (newEmail == null || !service.validateEmail(newEmail)) {
service.send(player, MessageKey.INVALID_NEW_EMAIL);
} else if (!oldEmail.equals(currentEmail)) {
service.send(player, MessageKey.INVALID_OLD_EMAIL);
} else if (dataSource.isEmailStored(newEmail)) {
} else if (!service.isEmailFreeForRegistration(newEmail, player)) {
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else {
saveNewEmail(auth);
@ -62,7 +61,6 @@ public class AsyncChangeEmail implements Process {
service.send(player, MessageKey.EMAIL_CHANGED_SUCCESS);
} else {
service.send(player, MessageKey.ERROR);
auth.setEmail(newEmail);
}
}

View File

@ -14,23 +14,27 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType;
import org.apache.commons.lang.reflect.MethodUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
/**
*/
public class AsynchronousJoin implements Process {
@ -42,6 +46,9 @@ public class AsynchronousJoin implements Process {
private final ProcessService service;
private final PlayerCache playerCache;
private final boolean disableCollisions = MethodUtils
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database, PlayerCache playerCache,
ProcessService service) {
this.player = player;
@ -62,14 +69,14 @@ public class AsynchronousJoin implements Process {
service.getPluginHooks().setEssentialsSocialSpyStatus(player, false);
}
final String ip = service.getIpAddressManager().getPlayerIp(player);
if (isNameRestricted(name, ip, player.getAddress().getHostName(), service.getSettings())) {
final String ip = Utils.getPlayerIp(player);
if (isNameRestricted(name, ip, player.getAddress().getHostName())) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true);
player.kickPlayer(service.retrieveSingleMessage(MessageKey.NOT_OWNER_ERROR));
if (Settings.banUnsafeIp) {
if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) {
plugin.getServer().banIP(ip);
}
}
@ -80,7 +87,7 @@ public class AsynchronousJoin implements Process {
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !"127.0.0.1".equalsIgnoreCase(ip)
&& !"localhost".equalsIgnoreCase(ip)
&& hasJoinedIp(player.getName(), ip, service.getSettings())) {
&& hasJoinedIp(player.getName(), ip)) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
@ -89,10 +96,14 @@ public class AsynchronousJoin implements Process {
});
return;
}
// Prevent player collisions in 1.9
if (disableCollisions) {
((LivingEntity) player).setCollidable(false);
}
final Location spawnLoc = service.getSpawnLoader().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) {
if (!Settings.noTeleport) {
if (!service.getProperty(RestrictionSettings.NO_TELEPORT)) {
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
@ -111,12 +122,12 @@ public class AsynchronousJoin implements Process {
LimboCache.getInstance().updateLimboPlayer(player);
// protect inventory
if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) {
if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN) && plugin.inventoryProtector != null) {
ProtectInventoryEvent ev = new ProtectInventoryEvent(player);
plugin.getServer().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player);
if (!Settings.noConsoleSpam) {
if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + "...");
}
}
@ -134,7 +145,7 @@ public class AsynchronousJoin implements Process {
service.send(player, MessageKey.SESSION_RECONNECTION);
plugin.getManagement().performLogin(player, "dontneed", true);
return;
} else if (Settings.sessionExpireOnIpChange) {
} else if (service.getProperty(PluginSettings.SESSIONS_EXPIRE_ON_IP_CHANGE)) {
service.send(player, MessageKey.SESSION_EXPIRED);
}
}
@ -142,7 +153,7 @@ public class AsynchronousJoin implements Process {
if (!Settings.unRegisteredGroup.isEmpty()) {
Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
}
if (!Settings.isForcedRegistrationEnabled) {
if (!service.getProperty(RegistrationSettings.FORCE)) {
return;
}
@ -173,12 +184,13 @@ public class AsynchronousJoin implements Process {
@Override
public void run() {
player.setOp(false);
if (Settings.isRemoveSpeedEnabled) {
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
&& service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f);
}
player.setNoDamageTicks(registrationTimeout);
if (service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
if (plugin.getPluginHooks().isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
player.performCommand("motd");
}
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
@ -200,12 +212,13 @@ public class AsynchronousJoin implements Process {
if (isAuthAvailable) {
msg = MessageKey.LOGIN_MESSAGE;
} else {
msg = Settings.emailRegistration
msg = service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)
? MessageKey.REGISTER_EMAIL_MESSAGE
: MessageKey.REGISTER_MESSAGE;
}
if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) {
BukkitTask msgTask = service.runTask(new MessageTask(plugin, name, msg, msgInterval));
BukkitTask msgTask = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
name, msg, msgInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgTask);
}
}
@ -266,24 +279,22 @@ public class AsynchronousJoin implements Process {
* @param name The name to check
* @param ip The IP address of the player
* @param domain The hostname of the IP address
* @param settings The settings instance
* @return True if the name is restricted (IP/domain is not allowed for the given name),
* false if the restrictions are met or if the name has no restrictions to it
*/
private static boolean isNameRestricted(String name, String ip, String domain, NewSetting settings) {
if (!settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
private boolean isNameRestricted(String name, String ip, String domain) {
if (!service.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
return false;
}
boolean nameFound = false;
for (String entry : settings.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
for (String entry : service.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
String[] args = entry.split(";");
String testName = args[0];
String testIp = args[1];
if (testName.equalsIgnoreCase(name)) {
nameFound = true;
if ((ip != null && testIp.equals(ip))
|| (domain != null && testIp.equalsIgnoreCase(domain))) {
if ((ip != null && testIp.equals(ip)) || (domain != null && testIp.equalsIgnoreCase(domain))) {
return false;
}
}
@ -291,14 +302,14 @@ public class AsynchronousJoin implements Process {
return nameFound;
}
private boolean hasJoinedIp(String name, String ip, NewSetting settings) {
private boolean hasJoinedIp(String name, String ip) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(service.getIpAddressManager().getPlayerIp(player))
for (Player player : service.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(Utils.getPlayerIp(player))
&& !player.getName().equalsIgnoreCase(name)) {
count++;
}
}
return count >= settings.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
return count >= service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
}
}

View File

@ -17,6 +17,7 @@ import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
@ -52,7 +53,7 @@ public class AsynchronousLogin implements Process {
this.forceLogin = forceLogin;
this.plugin = plugin;
this.database = data;
this.ip = service.getIpAddressManager().getPlayerIp(player);
this.ip = Utils.getPlayerIp(player);
this.service = service;
}
@ -96,8 +97,8 @@ public class AsynchronousLogin implements Process {
String[] msg = service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)
? service.retrieveMessage(MessageKey.REGISTER_EMAIL_MESSAGE)
: service.retrieveMessage(MessageKey.REGISTER_MESSAGE);
BukkitTask messageTask = service.runTask(
new MessageTask(plugin, name, msg, service.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
BukkitTask messageTask = service.runTask(new MessageTask(service.getBukkitService(),
name, msg, service.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
limboPlayer.setMessageTask(messageTask);
}
return null;
@ -166,11 +167,12 @@ public class AsynchronousLogin implements Process {
displayOtherAccounts(auth);
if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
&& (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
}
if (!Settings.noConsoleSpam) {
if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(realName + " logged in!");
}
@ -182,8 +184,7 @@ public class AsynchronousLogin implements Process {
// task, we schedule it in the end
// so that we can be sure, and have not to care if it might be
// processed in other order.
ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(
player, plugin, database, service.getSettings());
ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(player, plugin, database, service);
if (syncPlayerLogin.getLimbo() != null) {
if (syncPlayerLogin.getLimbo().getTimeoutTask() != null) {
syncPlayerLogin.getLimbo().getTimeoutTask().cancel();
@ -213,7 +214,7 @@ public class AsynchronousLogin implements Process {
}
private void displayOtherAccounts(PlayerAuth auth) {
if (!Settings.displayOtherAccounts || auth == null) {
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS) || auth == null) {
return;
}
@ -222,7 +223,7 @@ public class AsynchronousLogin implements Process {
return;
}
String message = "[AuthMe] " + StringUtils.join(", ", auths) + ".";
for (Player player : Utils.getOnlinePlayers()) {
for (Player player : service.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {

View File

@ -1,18 +1,7 @@
package fr.xephi.authme.process.login;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.potion.PotionEffectType;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.backup.JsonCache;
@ -24,14 +13,26 @@ import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.events.SpawnTeleportEvent;
import fr.xephi.authme.listener.AuthMePlayerListener;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType;
import org.apache.commons.lang.reflect.MethodUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.potion.PotionEffectType;
import static fr.xephi.authme.settings.properties.PluginSettings.KEEP_COLLISIONS_DISABLED;
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
public class ProcessSyncPlayerLogin implements Runnable {
public class ProcessSyncPlayerLogin implements Process {
private final LimboPlayer limbo;
private final Player player;
@ -40,7 +41,10 @@ public class ProcessSyncPlayerLogin implements Runnable {
private final AuthMe plugin;
private final PluginManager pm;
private final JsonCache playerCache;
private final NewSetting settings;
private final ProcessService service;
private final boolean restoreCollisions = MethodUtils
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
/**
* Constructor for ProcessSyncPlayerLogin.
@ -48,10 +52,9 @@ public class ProcessSyncPlayerLogin implements Runnable {
* @param player Player
* @param plugin AuthMe
* @param database DataSource
* @param settings The plugin settings
* @param service The process service
*/
public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
DataSource database, NewSetting settings) {
public ProcessSyncPlayerLogin(Player player, AuthMe plugin, DataSource database, ProcessService service) {
this.plugin = plugin;
this.pm = plugin.getServer().getPluginManager();
this.player = player;
@ -59,7 +62,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
this.limbo = LimboCache.getInstance().getLimboPlayer(name);
this.auth = database.getAuth(name);
this.playerCache = new JsonCache();
this.settings = settings;
this.service = service;
}
public LimboPlayer getLimbo() {
@ -92,7 +95,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
private void restoreSpeedEffects() {
if (settings.getProperty(RestrictionSettings.REMOVE_SPEED)) {
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT) && service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
player.setWalkSpeed(0.2F);
player.setFlySpeed(0.1F);
}
@ -107,10 +110,10 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
private void forceCommands() {
for (String command : Settings.forceCommands) {
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS)) {
player.performCommand(command.replace("%p", player.getName()));
}
for (String command : Settings.forceCommandsAsConsole) {
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS_AS_CONSOLE)) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command.replace("%p", player.getName()));
}
}
@ -148,10 +151,18 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
}
if (settings.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
if (restoreCollisions && !service.getProperty(KEEP_COLLISIONS_DISABLED)) {
player.setCollidable(true);
}
if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
restoreInventory();
}
if (service.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && plugin.tablistHider != null) {
plugin.tablistHider.sendTablist(player);
}
// Cleanup no longer used temporary data
LimboCache.getInstance().deleteLimboPlayer(name);
if (playerCache.doesCacheExist(player)) {
@ -163,7 +174,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
String jm = AuthMePlayerListener.joinMessage.get(name);
if (jm != null) {
if (!jm.isEmpty()) {
for (Player p : Utils.getOnlinePlayers()) {
for (Player p : service.getOnlinePlayers()) {
if (p.isOnline()) {
p.sendMessage(jm);
}
@ -173,24 +184,24 @@ public class ProcessSyncPlayerLogin implements Runnable {
}
restoreSpeedEffects();
if (settings.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
player.removePotionEffect(PotionEffectType.BLINDNESS);
}
// The Login event now fires (as intended) after everything is processed
Bukkit.getServer().getPluginManager().callEvent(new LoginEvent(player));
player.saveData();
if (settings.getProperty(HooksSettings.BUNGEECORD)) {
if (service.getProperty(HooksSettings.BUNGEECORD)) {
sendBungeeMessage();
}
// Login is done, display welcome message
if (settings.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
if (settings.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
for (String s : settings.getWelcomeMessage()) {
if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
for (String s : service.getSettings().getWelcomeMessage()) {
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
}
} else {
for (String s : settings.getWelcomeMessage()) {
for (String s : service.getSettings().getWelcomeMessage()) {
player.sendMessage(plugin.replaceAllInfo(s, player));
}
}
@ -198,15 +209,15 @@ public class ProcessSyncPlayerLogin implements Runnable {
// Login is now finished; we can force all commands
forceCommands();
sendTo();
}
private void sendTo() {
if (!settings.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) {
if (!service.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect");
out.writeUTF(settings.getProperty(HooksSettings.BUNGEECORD_SERVER));
out.writeUTF(service.getProperty(HooksSettings.BUNGEECORD_SERVER));
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
}
}

View File

@ -74,7 +74,8 @@ public class ProcessSynchronousPlayerLogout implements Process {
BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), timeOut);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTask(id);
}
BukkitTask msgT = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
BukkitTask msgT = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
name, MessageKey.LOGIN_MESSAGE, interval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgT);
if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject();

View File

@ -43,7 +43,7 @@ public class AsynchronousQuit implements Process {
return;
}
String ip = service.getIpAddressManager().getPlayerIp(player);
String ip = Utils.getPlayerIp(player);
if (PlayerCache.getInstance().isAuthenticated(name)) {
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
@ -94,7 +94,6 @@ public class AsynchronousQuit implements Process {
database.setUnlogged(name);
}
service.getIpAddressManager().removeCache(player.getName());
if (plugin.isEnabled()) {
service.scheduleSyncDelayedTask(new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
}

View File

@ -38,9 +38,6 @@ public class ProcessSyncronousPlayerQuit implements Runnable {
if (needToChange) {
player.setOp(isOp);
}
try {
player.getVehicle().eject();
} catch (Exception ignored) {
}
player.leaveVehicle();
}
}

View File

@ -12,8 +12,13 @@ import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.TwoFactor;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -30,43 +35,36 @@ public class AsyncRegister implements Process {
private final String email;
private final AuthMe plugin;
private final DataSource database;
private final PlayerCache playerCache;
private final ProcessService service;
public AsyncRegister(Player player, String password, String email, AuthMe plugin, DataSource data,
ProcessService service) {
PlayerCache playerCache, ProcessService service) {
this.player = player;
this.password = password;
this.name = player.getName().toLowerCase();
this.email = email;
this.plugin = plugin;
this.database = data;
this.ip = service.getIpAddressManager().getPlayerIp(player);
this.ip = Utils.getPlayerIp(player);
this.playerCache = playerCache;
this.service = service;
}
private boolean preRegisterCheck() {
String passLow = password.toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(name)) {
if (playerCache.isAuthenticated(name)) {
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return false;
} else if (!Settings.isRegistrationEnabled) {
} else if (!service.getProperty(RegistrationSettings.IS_ENABLED)) {
service.send(player, MessageKey.REGISTRATION_DISABLED);
return false;
}
//check the password safety only if it's not a automatically generated password
if (service.getProperty(SecuritySettings.PASSWORD_HASH) != HashAlgorithm.TWO_FACTOR) {
if (!passLow.matches(Settings.getPassRegex)) {
service.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return false;
} else if (passLow.equalsIgnoreCase(player.getName())) {
service.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR);
return false;
} else if (password.length() < Settings.getPasswordMinLen || password.length() > Settings.passwordMaxLength) {
service.send(player, MessageKey.INVALID_PASSWORD_LENGTH);
return false;
} else if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(password.toLowerCase())) {
service.send(player, MessageKey.PASSWORD_UNSAFE_ERROR);
MessageKey passwordError = service.validatePassword(password, player.getName());
if (passwordError != null) {
service.send(player, passwordError);
return false;
}
}
@ -75,15 +73,17 @@ public class AsyncRegister implements Process {
if (database.isAuthAvailable(name)) {
service.send(player, MessageKey.NAME_ALREADY_REGISTERED);
return false;
} else if(Settings.getmaxRegPerIp > 0
&& !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost")
}
final int maxRegPerIp = service.getProperty(RestrictionSettings.MAX_REGISTRATION_PER_IP);
if (maxRegPerIp > 0
&& !"127.0.0.1".equalsIgnoreCase(ip)
&& !"localhost".equalsIgnoreCase(ip)
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
int maxReg = Settings.getmaxRegPerIp;
List<String> otherAccounts = database.getAllAuthsByIp(ip);
if (otherAccounts.size() >= maxReg) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
Integer.toString(otherAccounts.size()), StringUtils.join(", ", otherAccounts.toString()));
if (otherAccounts.size() >= maxRegPerIp) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxRegPerIp),
Integer.toString(otherAccounts.size()), StringUtils.join(", ", otherAccounts));
return false;
}
}
@ -102,12 +102,12 @@ public class AsyncRegister implements Process {
}
private void emailRegister() {
if (Settings.getmaxRegPerEmail > 0
final int maxRegPerEmail = service.getProperty(EmailSettings.MAX_REG_PER_EMAIL);
if (maxRegPerEmail > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
int maxReg = Settings.getmaxRegPerEmail;
int otherAccounts = database.countAuthsByEmail(email);
if (otherAccounts >= maxReg) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
if (otherAccounts >= maxRegPerEmail) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxRegPerEmail),
Integer.toString(otherAccounts), "@");
return;
}

View File

@ -52,13 +52,13 @@ public class ProcessSyncEmailRegister implements Process {
limbo.setTimeoutTask(id);
}
BukkitTask messageTask = service.runTask(new MessageTask(
service.getAuthMe(), name, service.retrieveMessage(MessageKey.LOGIN_MESSAGE), msgInterval));
service.getBukkitService(), name, service.retrieveMessage(MessageKey.LOGIN_MESSAGE), msgInterval));
limbo.setMessageTask(messageTask);
}
player.saveData();
if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
ConsoleLogger.info(player.getName() + " registered " + Utils.getPlayerIp(player));
}
}

View File

@ -12,9 +12,11 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils;
@ -23,12 +25,15 @@ import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
import static fr.xephi.authme.settings.properties.RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
/**
*/
public class ProcessSyncPasswordRegister implements Process {
protected final Player player;
protected final String name;
private final Player player;
private final String name;
private final AuthMe plugin;
private final ProcessService service;
@ -49,27 +54,33 @@ public class ProcessSyncPasswordRegister implements Process {
}
private void forceCommands() {
for (String command : Settings.forceRegisterCommands) {
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS)) {
player.performCommand(command.replace("%p", player.getName()));
}
for (String command : Settings.forceRegisterCommandsAsConsole) {
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS_AS_CONSOLE)) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
command.replace("%p", player.getName()));
command.replace("%p", player.getName()));
}
}
private void forceLogin(Player player) {
/**
* Request that the player log in.
*
* @param player the player
*/
private void requestLogin(Player player) {
Utils.teleportToSpawn(player);
LimboCache cache = LimboCache.getInstance();
cache.updateLimboPlayer(player);
int delay = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
int delay = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitTask task;
if (delay != 0) {
task = service.runTaskLater(new TimeoutTask(service.getAuthMe(), name, player), delay);
cache.getLimboPlayer(name).setTimeoutTask(task);
}
task = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
task = service.runTask(new MessageTask(service.getBukkitService(), plugin.getMessages(),
name, MessageKey.LOGIN_MESSAGE, interval));
cache.getLimboPlayer(name).setMessageTask(task);
if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject();
@ -80,11 +91,15 @@ public class ProcessSyncPasswordRegister implements Process {
public void run() {
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
if (limbo != null) {
if (service.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && plugin.tablistHider != null) {
plugin.tablistHider.sendTablist(player);
}
Utils.teleportToSpawn(player);
if (Settings.protectInventoryBeforeLogInEnabled && plugin.inventoryProtector != null) {
if (service.getProperty(HIDE_TABLIST_BEFORE_LOGIN) && plugin.inventoryProtector != null) {
RestoreInventoryEvent event = new RestoreInventoryEvent(player);
Bukkit.getPluginManager().callEvent(event);
service.callEvent(event);
if (!event.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player);
}
@ -99,7 +114,7 @@ public class ProcessSyncPasswordRegister implements Process {
service.send(player, MessageKey.REGISTER_SUCCESS);
if (!Settings.getmailAccount.isEmpty()) {
if (!service.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
}
@ -111,42 +126,29 @@ public class ProcessSyncPasswordRegister implements Process {
plugin.getServer().getPluginManager().callEvent(new LoginEvent(player));
player.saveData();
if (!Settings.noConsoleSpam) {
ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(player.getName() + " registered " + Utils.getPlayerIp(player));
}
// Kick Player after Registration is enabled, kick the player
if (Settings.forceRegKick) {
if (service.getProperty(RegistrationSettings.FORCE_KICK_AFTER_REGISTER)) {
player.kickPlayer(service.retrieveSingleMessage(MessageKey.REGISTER_SUCCESS));
return;
}
// Register is finish and player is logged, display welcome message
if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
for (String s : service.getSettings().getWelcomeMessage()) {
plugin.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
}
} else {
for (String s : service.getSettings().getWelcomeMessage()) {
player.sendMessage(plugin.replaceAllInfo(s, player));
}
}
}
// Register is now finished; we can force all commands
forceCommands();
// Request Login after Registration
if (Settings.forceRegLogin) {
forceLogin(player);
// Request login after registration
if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
requestLogin(player);
return;
}
if (Settings.bungee) {
if (service.getProperty(HooksSettings.BUNGEECORD)) {
sendBungeeMessage();
}
// Register is now finished; we can force all commands
forceCommands();
sendTo();
}

View File

@ -20,7 +20,6 @@ import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
public class AsynchronousUnregister implements Process {
@ -73,13 +72,12 @@ public class AsynchronousUnregister implements Process {
LimboCache.getInstance().addLimboPlayer(player);
LimboPlayer limboPlayer = LimboCache.getInstance().getLimboPlayer(name);
int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitScheduler scheduler = plugin.getServer().getScheduler();
if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut);
BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), timeOut);
limboPlayer.setTimeoutTask(id);
}
limboPlayer.setMessageTask(scheduler.runTask(plugin,
new MessageTask(plugin, name, MessageKey.REGISTER_MESSAGE, interval)));
limboPlayer.setMessageTask(service.runTask(new MessageTask(service.getBukkitService(),
plugin.getMessages(), name, MessageKey.REGISTER_MESSAGE, interval)));
service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
return;
@ -99,7 +97,6 @@ public class AsynchronousUnregister implements Process {
}
service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
Utils.teleportToSpawn(player);
} else {
service.send(player, MessageKey.WRONG_PASSWORD);
}

View File

@ -8,46 +8,75 @@ import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.plugin.PluginManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Manager class for password-related operations.
*/
public class PasswordSecurity {
private final NewSetting settings;
private HashAlgorithm algorithm;
private boolean supportOldAlgorithm;
private final DataSource dataSource;
private final PluginManager pluginManager;
public PasswordSecurity(DataSource dataSource, NewSetting settings, PluginManager pluginManager) {
this.settings = settings;
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
this.dataSource = dataSource;
this.pluginManager = pluginManager;
}
/**
* Compute the hash of the configured algorithm for the given password and username.
*
* @param password The password to hash
* @param playerName The player's name
*
* @return The password hash
*/
public HashedPassword computeHash(String password, String playerName) {
return computeHash(algorithm, password, playerName);
}
public HashedPassword computeHash(HashAlgorithm algorithm, String password, String playerName) {
String playerLowerCase = playerName.toLowerCase();
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerLowerCase);
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerLowerCase);
return method.computeHash(password, playerLowerCase);
}
/**
* Check if the given password matches the player's stored password.
*
* @param password The password to check
* @param playerName The player to check for
*
* @return True if the password is correct, false otherwise
*/
public boolean comparePassword(String password, String playerName) {
HashedPassword auth = dataSource.getPassword(playerName);
return auth != null && comparePassword(password, auth, playerName);
}
/**
* Check if the given password matches the given hashed password.
*
* @param password The password to check
* @param hashedPassword The hashed password to check against
* @param playerName The player to check for
*
* @return True if the password matches, false otherwise
*/
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
EncryptionMethod method = initializeEncryptionMethod(algorithm, playerName);
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
String playerLowerCase = playerName.toLowerCase();
return methodMatches(method, password, hashedPassword, playerLowerCase)
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase);
}
public void reload(NewSetting settings) {
/**
* Reload the configuration.
*/
public void reload() {
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
}
@ -63,11 +92,10 @@ public class PasswordSecurity {
*
* @return True if there was a password match with another encryption method, false otherwise
*/
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword,
String playerName) {
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword, String playerName) {
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
EncryptionMethod method = initializeEncryptionMethod(algorithm, settings);
if (methodMatches(method, password, hashedPassword, playerName)) {
hashPasswordForNewAlgorithm(password, playerName);
return true;
@ -85,6 +113,7 @@ public class PasswordSecurity {
* @param password The password to check
* @param hashedPassword The hash to check against
* @param playerName The name of the player
*
* @return True if the password matched, false otherwise
*/
private static boolean methodMatches(EncryptionMethod method, String password,
@ -103,33 +132,45 @@ public class PasswordSecurity {
*
* @return The encryption method
*/
private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm, String playerName) {
EncryptionMethod method = initializeEncryptionMethodWithoutEvent(algorithm);
private EncryptionMethod initializeEncryptionMethodWithEvent(HashAlgorithm algorithm, String playerName) {
EncryptionMethod method = initializeEncryptionMethod(algorithm, settings);
PasswordEncryptionEvent event = new PasswordEncryptionEvent(method, playerName);
pluginManager.callEvent(event);
return event.getMethod();
}
/**
* Initialize the encryption method corresponding to the given hash algorithm.
* Initialize the encryption method associated with the given hash algorithm.
*
* @param algorithm The algorithm to retrieve the encryption method for
* @param settings The settings instance to pass to the constructor if required
*
* @return The associated encryption method
* @return The associated encryption method, or null if CUSTOM / deprecated
*/
private static EncryptionMethod initializeEncryptionMethodWithoutEvent(HashAlgorithm algorithm) {
public static EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm,
NewSetting settings) {
try {
return HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)
? null
: algorithm.getClazz().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) {
return null;
}
Constructor<?> constructor = algorithm.getClazz().getConstructors()[0];
Class<?>[] parameters = constructor.getParameterTypes();
if (parameters.length == 0) {
return (EncryptionMethod) constructor.newInstance();
} else if (parameters.length == 1 && parameters[0] == NewSetting.class) {
return (EncryptionMethod) constructor.newInstance(settings);
} else {
throw new UnsupportedOperationException("Did not find default constructor or constructor with settings "
+ "parameter in class " + algorithm.getClazz().getSimpleName());
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new UnsupportedOperationException("Constructor for '" + algorithm.getClazz().getSimpleName()
+ "' could not be invoked. (Is there no default constructor?)", e);
}
}
private void hashPasswordForNewAlgorithm(String password, String playerName) {
HashedPassword hashedPassword = initializeEncryptionMethod(algorithm, playerName)
HashedPassword hashedPassword = initializeEncryptionMethodWithEvent(algorithm, playerName)
.computeHash(password, playerName);
dataSource.updatePassword(playerName, hashedPassword);
}

View File

@ -5,7 +5,8 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.StringUtils;
@ -13,6 +14,12 @@ import fr.xephi.authme.util.StringUtils;
@HasSalt(value = SaltType.TEXT) // length depends on Settings.bCryptLog2Rounds
public class BCRYPT implements EncryptionMethod {
private final int bCryptLog2Rounds;
public BCRYPT(NewSetting settings) {
this.bCryptLog2Rounds = settings.getProperty(HooksSettings.BCRYPT_LOG2_ROUND);
}
@Override
public String computeHash(String password, String salt, String name) {
return BCryptService.hashpw(password, salt);
@ -36,7 +43,7 @@ public class BCRYPT implements EncryptionMethod {
@Override
public String generateSalt() {
return BCryptService.gensalt(Settings.bCryptLog2Rounds);
return BCryptService.gensalt(bCryptLog2Rounds);
}
@Override

View File

@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
import fr.xephi.authme.util.StringUtils;
import javax.xml.bind.DatatypeConverter;
@ -31,8 +32,8 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
try {
iterations = Integer.parseInt(line[1]);
} catch (NumberFormatException e) {
ConsoleLogger.logException("Could not read number of rounds in '" + hashedPassword.getHash()
+ " for CryptPBKDF2Django", e);
ConsoleLogger.showError("Could not read number of rounds for CryptPBKDF2Django:"
+ StringUtils.formatException(e));
return false;
}
String salt = line[2];

View File

@ -2,6 +2,10 @@ package fr.xephi.authme.security.crypts;
/**
* Public interface for custom password encryption methods.
* <p>
* Note that {@link fr.xephi.authme.security.PasswordSecurity} requires classes implementing this interface
* to either have the default constructor or an accessible constructor with one parameter of type
* {@link fr.xephi.authme.settings.NewSetting}.
*/
public interface EncryptionMethod {
@ -31,9 +35,9 @@ public interface EncryptionMethod {
/**
* Check whether the given hash matches the clear-text password.
*
* @param password The clear-text password to verify
* @param password The clear-text password to verify
* @param hashedPassword The hash to check the password against
* @param name The player name to do the check for (sometimes required for generating the salt)
* @param name The player name to do the check for (sometimes required for generating the salt)
*
* @return True if the password matches, false otherwise
*/

View File

@ -19,7 +19,7 @@ public class MYBB extends SeparateSaltMethod {
@Override
public String generateSalt() {
return RandomString.generateHex(8);
return RandomString.generateLowerUpper(8);
}
}

View File

@ -5,7 +5,8 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.SecuritySettings;
import static fr.xephi.authme.security.HashUtils.md5;
@ -13,6 +14,12 @@ import static fr.xephi.authme.security.HashUtils.md5;
@HasSalt(value = SaltType.TEXT) // length defined by Settings.saltLength
public class SALTED2MD5 extends SeparateSaltMethod {
private final int saltLength;
public SALTED2MD5(NewSetting settings) {
saltLength = settings.getProperty(SecuritySettings.DOUBLE_MD5_SALT_LENGTH);
}
@Override
public String computeHash(String password, String salt, String name) {
return md5(md5(password) + salt);
@ -20,7 +27,7 @@ public class SALTED2MD5 extends SeparateSaltMethod {
@Override
public String generateSalt() {
return RandomString.generateHex(Settings.saltLength);
return RandomString.generateHex(saltLength);
}
}

View File

@ -8,10 +8,8 @@ import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.Wrapper;
import org.bukkit.configuration.file.FileConfiguration;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -22,55 +20,27 @@ import java.util.regex.Pattern;
*/
public final class Settings {
public static final File PLUGIN_FOLDER = Wrapper.getInstance().getDataFolder();
public static final File MODULE_FOLDER = new File(PLUGIN_FOLDER, "modules");
public static final File CACHE_FOLDER = new File(PLUGIN_FOLDER, "cache");
// This is not an option!
public static boolean antiBotInAction = false;
public static List<String> allowCommands;
public static List<String> getJoinPermissions;
public static List<String> getUnrestrictedName;
public static List<String> getRestrictedIp;
public static List<String> getForcedWorlds;
public static List<String> countries;
public static List<String> countriesBlacklist;
public static List<String> forceCommands;
public static List<String> forceCommandsAsConsole;
public static List<String> forceRegisterCommands;
public static List<String> forceRegisterCommandsAsConsole;
public static List<String> unsafePasswords;
public static HashAlgorithm getPasswordHash;
public static Pattern nickPattern;
public static boolean useLogging = false;
public static boolean isChatAllowed, isPermissionCheckEnabled, isRegistrationEnabled,
public static boolean isPermissionCheckEnabled,
isForcedRegistrationEnabled, isTeleportToSpawnEnabled,
isSessionsEnabled, isAllowRestrictedIp,
isMovementAllowed, isKickNonRegisteredEnabled,
isForceSingleSessionEnabled, isForceSpawnLocOnJoinEnabled,
isSaveQuitLocationEnabled, isForceSurvivalModeEnabled,
isKickOnWrongPasswordEnabled, enablePasswordConfirmation,
protectInventoryBeforeLogInEnabled, isStopEnabled, reloadSupport,
rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts,
emailRegistration, multiverse, bungee,
banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange,
disableSocialSpy, useEssentialsMotd,
enableProtection, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin,
checkVeryGames, removeJoinMessage, removeLeaveMessage, delayJoinMessage,
noTeleport, hideTablistBeforeLogin, denyTabcompleteBeforeLogin,
kickPlayersBeforeStopping, allowAllCommandsIfRegIsOptional,
customAttributes, isRemoveSpeedEnabled, preventOtherCase;
isSaveQuitLocationEnabled, protectInventoryBeforeLogInEnabled,
isStopEnabled, reloadSupport, rakamakUseIp,
removePassword, multiverse, bungee,
enableProtection, forceRegLogin, noTeleport,
allowAllCommandsIfRegIsOptional, isRemoveSpeedEnabled;
public static String getNickRegex, getUnloggedinGroup,
unRegisteredGroup,
backupWindowsPath, getRegisteredGroup,
rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld,
spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo;
public static int getWarnMessageInterval, getSessionTimeout,
getRegistrationTimeout, getMaxNickLength, getMinNickLength,
getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength,
getMailPort, maxLoginTry, captchaLength, saltLength,
getmaxRegPerEmail, bCryptLog2Rounds, getMaxLoginPerIp, getMaxJoinPerIp;
unRegisteredGroup, backupWindowsPath, getRegisteredGroup,
rakamakUsers, rakamakUsersIp, defaultWorld, crazyloginFileName;
public static int getSessionTimeout, getMaxNickLength, getMinNickLength,
getNonActivatedGroup, maxLoginTry, captchaLength, getMaxLoginPerIp;
protected static FileConfiguration configFile;
/**
@ -85,32 +55,19 @@ public final class Settings {
private static void loadVariables() {
isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK);
isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true);
isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true);
isForcedRegistrationEnabled = load(RegistrationSettings.FORCE);
isTeleportToSpawnEnabled = load(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN);
getWarnMessageInterval = load(RegistrationSettings.MESSAGE_INTERVAL);
isSessionsEnabled = load(PluginSettings.SESSIONS_ENABLED);
getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10);
getRegistrationTimeout = load(RestrictionSettings.TIMEOUT);
isChatAllowed = load(RestrictionSettings.ALLOW_CHAT);
getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20);
getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3);
getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4);
getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*");
nickPattern = Pattern.compile(getNickRegex);
isAllowRestrictedIp = load(RestrictionSettings.ENABLE_RESTRICTED_USERS);
getRestrictedIp = load(RestrictionSettings.ALLOWED_RESTRICTED_USERS);
isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false);
isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true);
getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100);
getJoinPermissions = configFile.getStringList("GroupOptions.Permissions.PermissionsOnJoin");
isKickOnWrongPasswordEnabled = configFile.getBoolean("settings.restrictions.kickOnWrongPassword", false);
isKickNonRegisteredEnabled = configFile.getBoolean("settings.restrictions.kickNonRegistered", false);
isForceSingleSessionEnabled = configFile.getBoolean("settings.restrictions.ForceSingleSession", true);
isForceSpawnLocOnJoinEnabled = configFile.getBoolean("settings.restrictions.ForceSpawnLocOnJoinEnabled", false);
isRemoveSpeedEnabled = load(RestrictionSettings.REMOVE_SPEED);
isForceSingleSessionEnabled = load(RestrictionSettings.FORCE_SINGLE_SESSION);
isForceSpawnLocOnJoinEnabled = load(RestrictionSettings.FORCE_SPAWN_LOCATION_AFTER_LOGIN);
isSaveQuitLocationEnabled = configFile.getBoolean("settings.restrictions.SaveQuitLocation", false);
isForceSurvivalModeEnabled = configFile.getBoolean("settings.GameMode.ForceSurvivalMode", false);
getmaxRegPerIp = configFile.getInt("settings.restrictions.maxRegPerIp", 1);
getPasswordHash = load(SecuritySettings.PASSWORD_HASH);
getUnloggedinGroup = load(SecuritySettings.UNLOGGEDIN_GROUP);
getNonActivatedGroup = configFile.getInt("ExternalBoardOptions.nonActivedUserGroup", -1);
@ -122,18 +79,12 @@ public final class Settings {
}
getRegisteredGroup = configFile.getString("GroupOptions.RegisteredPlayerGroup", "");
enablePasswordConfirmation = load(RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION);
protectInventoryBeforeLogInEnabled = load(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN);
denyTabcompleteBeforeLogin = load(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN);
hideTablistBeforeLogin = load(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN);
passwordMaxLength = load(SecuritySettings.MAX_PASSWORD_LENGTH);
backupWindowsPath = configFile.getString("BackupSystem.MysqlWindowsPath", "C:\\Program Files\\MySQL\\MySQL Server 5.1\\");
isStopEnabled = configFile.getBoolean("Security.SQLProblem.stopServer", true);
reloadSupport = configFile.getBoolean("Security.ReloadCommand.useReloadCommandSupport", true);
allowAllCommandsIfRegIsOptional = configFile.getBoolean("settings.restrictions.allowAllCommandsIfRegistrationIsOptional", false);
allowAllCommandsIfRegIsOptional = load(RestrictionSettings.ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL);
allowCommands = new ArrayList<>();
allowCommands.addAll(Arrays.asList("/login", "/l", "/register", "/reg", "/email", "/captcha"));
for (String cmd : configFile.getStringList("settings.restrictions.allowCommands")) {
@ -146,71 +97,20 @@ public final class Settings {
rakamakUsers = configFile.getString("Converter.Rakamak.fileName", "users.rak");
rakamakUsersIp = configFile.getString("Converter.Rakamak.ipFileName", "UsersIp.rak");
rakamakUseIp = configFile.getBoolean("Converter.Rakamak.useIp", false);
noConsoleSpam = load(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE);
removePassword = configFile.getBoolean("Security.console.removePassword", true);
getmailAccount = configFile.getString("Email.mailAccount", "");
getMailPort = configFile.getInt("Email.mailPort", 465);
getRecoveryPassLength = configFile.getInt("Email.RecoveryPasswordLength", 8);
displayOtherAccounts = configFile.getBoolean("settings.restrictions.displayOtherAccounts", true);
maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5);
captchaLength = configFile.getInt("Security.captcha.captchaLength", 5);
emailRegistration = load(RegistrationSettings.USE_EMAIL_REGISTRATION);
saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8);
getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1);
multiverse = load(HooksSettings.MULTIVERSE);
bungee = configFile.getBoolean("Hooks.bungeecord", false);
bungee = load(HooksSettings.BUNGEECORD);
getForcedWorlds = configFile.getStringList("settings.restrictions.ForceSpawnOnTheseWorlds");
banUnsafeIp = configFile.getBoolean("settings.restrictions.banUnsafedIP", false);
doubleEmailCheck = configFile.getBoolean("settings.registration.doubleEmailCheck", false);
sessionExpireOnIpChange = configFile.getBoolean("settings.sessions.sessionExpireOnIpChange", true);
useLogging = configFile.getBoolean("Security.console.logConsole", false);
disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true);
bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10);
useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false);
defaultWorld = configFile.getString("Purge.defaultWorld", "world");
enableProtection = configFile.getBoolean("Protection.enableProtection", false);
countries = configFile.getStringList("Protection.countries");
forceCommands = configFile.getStringList("settings.forceCommands");
forceCommandsAsConsole = configFile.getStringList("settings.forceCommandsAsConsole");
recallEmail = configFile.getBoolean("Email.recallPlayers", false);
useWelcomeMessage = load(RegistrationSettings.USE_WELCOME_MESSAGE);
unsafePasswords = configFile.getStringList("settings.security.unsafePasswords");
countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist");
broadcastWelcomeMessage = load(RegistrationSettings.BROADCAST_WELCOME_MESSAGE);
forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false);
forceRegLogin = load(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER);
spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY);
getMaxLoginPerIp = load(RestrictionSettings.MAX_LOGIN_PER_IP);
getMaxJoinPerIp = load(RestrictionSettings.MAX_JOIN_PER_IP);
checkVeryGames = load(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE);
removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE);
delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE);
noTeleport = load(RestrictionSettings.NO_TELEPORT);
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*");
forceRegisterCommands = configFile.getStringList("settings.forceRegisterCommands");
forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole");
customAttributes = configFile.getBoolean("Hooks.customAttributes");
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
kickPlayersBeforeStopping = configFile.getBoolean("Security.stop.kickPlayersBeforeStopping", true);
sendPlayerTo = configFile.getString("Hooks.sendPlayerTo", "");
}
/**
* Method switchAntiBotMod.
*
* @param mode boolean
*/
public static void switchAntiBotMod(boolean mode) {
if (mode) {
isKickNonRegisteredEnabled = true;
antiBotInAction = true;
} else {
isKickNonRegisteredEnabled = configFile.getBoolean("settings.restrictions.kickNonRegistered", false);
antiBotInAction = false;
}
}
/**

View File

@ -59,7 +59,7 @@ public class SettingsMigrationService {
private static boolean hasDeprecatedProperties(FileConfiguration configuration) {
String[] deprecatedProperties = {
"Converter.Rakamak.newPasswordHash", "Hooks.chestshop", "Hooks.legacyChestshop", "Hooks.notifications",
"Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt"};
"Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt", "VeryGames"};
for (String deprecatedPath : deprecatedProperties) {
if (configuration.contains(deprecatedPath)) {
return true;

View File

@ -35,10 +35,6 @@ public class HooksSettings implements SettingsClass {
public static final Property<Boolean> CACHE_CUSTOM_ATTRIBUTES =
newProperty("Hooks.customAttributes", false);
@Comment("These features are only available on VeryGames Server Provider")
public static final Property<Boolean> ENABLE_VERYGAMES_IP_CHECK =
newProperty("VeryGames.enableIpCheck", false);
@Comment({
"-1 means disabled. If you want that only activated players",
"can log into your server, you can set here the group number",

View File

@ -53,6 +53,12 @@ public class PluginSettings implements SettingsClass {
public static final Property<Boolean> ENABLE_PERMISSION_CHECK =
newProperty("permission.EnablePermissionCheck", false);
@Comment({
"Keeps collisions disabled for logged players",
"Works only with MC 1.9"
})
public static final Property<Boolean> KEEP_COLLISIONS_DISABLED =
newProperty("settings.restrictions.keepCollisionsDisabled", false);
private PluginSettings() {
}

View File

@ -67,7 +67,7 @@ public class RegistrationSettings implements SettingsClass {
newListProperty("settings.forceRegisterCommandsAsConsole");
@Comment({
"Enable to display the welcome message (welcome.txt) after a registration or a login",
"Enable to display the welcome message (welcome.txt) after a login",
"You can use colors in this welcome.txt + some replaced strings:",
"{PLAYER}: player name, {ONLINE}: display number of online players, {MAXPLAYERS}: display server slots,",
"{IP}: player ip, {LOGINS}: number of players logged, {WORLD}: player current world, {SERVER}: server name",

View File

@ -12,15 +12,19 @@ import static fr.xephi.authme.settings.domain.Property.newProperty;
public class RestrictionSettings implements SettingsClass {
@Comment({
"Can not authenticated players chat and see the chat log?",
"Can not authenticated players chat?",
"Keep in mind that this feature also blocks all commands not",
"listed in the list below."})
public static final Property<Boolean> ALLOW_CHAT =
newProperty("settings.restrictions.allowChat", false);
@Comment("Hide the chat log from players who are not authenticated?")
public static final Property<Boolean> HIDE_CHAT =
newProperty("settings.restrictions.hideChat", false);
@Comment({
"Allow unlogged users to use all the commands if registration is not forced!",
"WARNING: use this only if you need it!)"})
"WARNING: use this only if you need it!"})
public static final Property<Boolean> ALLOW_ALL_COMMANDS_IF_REGISTRATION_IS_OPTIONAL =
newProperty("settings.restrictions.allowAllCommandsIfRegistrationIsOptional", false);
@ -29,8 +33,9 @@ public class RestrictionSettings implements SettingsClass {
newListProperty("settings.restrictions.allowCommands",
"login", "register", "l", "reg", "email", "captcha");
@Comment("Max number of allowed registrations per IP")
// TODO ljacqu 20160109: If 0 == unlimited, add this fact to the comment
@Comment({
"Max number of allowed registrations per IP",
"The value 0 means an unlimited number of registrations!"})
public static final Property<Integer> MAX_REGISTRATION_PER_IP =
newProperty("settings.restrictions.maxRegPerIp", 1);

View File

@ -38,7 +38,7 @@ public final class SettingsFieldRetriever {
for (Class<?> clazz : CONFIGURATION_CLASSES) {
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
Property property = getPropertyField(field);
Property<?> property = getPropertyField(field);
if (property != null) {
properties.put(property, getCommentsForField(field));
}
@ -64,7 +64,7 @@ public final class SettingsFieldRetriever {
field.setAccessible(true);
if (field.isAccessible() && Property.class.equals(field.getType()) && Modifier.isStatic(field.getModifiers())) {
try {
return (Property) field.get(null);
return (Property<?>) field.get(null);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not fetch field '" + field.getName() + "' from class '"
+ field.getDeclaringClass().getSimpleName() + "': " + StringUtils.formatException(e));

View File

@ -31,7 +31,7 @@ public class PropertyMap {
* @param property The property to add
* @param comments The comments associated to the property
*/
public void put(Property property, String[] comments) {
public void put(Property<?> property, String[] comments) {
comparator.add(property);
map.put(property, comments);
}

View File

@ -13,7 +13,7 @@ import java.util.Comparator;
* property, then "DataSource" properties will come before the "security" ones.</li>
* </ul>
*/
final class PropertyMapComparator implements Comparator<Property> {
final class PropertyMapComparator implements Comparator<Property<?>> {
private Node parent = Node.createRoot();
@ -22,12 +22,12 @@ final class PropertyMapComparator implements Comparator<Property> {
*
* @param property The property that is being added
*/
public void add(Property property) {
public void add(Property<?> property) {
parent.addNode(property.getPath());
}
@Override
public int compare(Property p1, Property p2) {
public int compare(Property<?> p1, Property<?> p2) {
return parent.compare(p1.getPath(), p2.getPath());
}

View File

@ -1,10 +1,10 @@
package fr.xephi.authme.task;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
@ -12,28 +12,27 @@ import org.bukkit.scheduler.BukkitTask;
*/
public class MessageTask implements Runnable {
private final AuthMe plugin;
private final BukkitService bukkitService;
private final String name;
private final String[] msg;
private final int interval;
/**
* Constructor for MessageTask.
*
* @param plugin AuthMe
* @param name String
* @param lines String[]
* @param interval int
/*
* Constructor.
*/
public MessageTask(AuthMe plugin, String name, String[] lines, int interval) {
this.plugin = plugin;
public MessageTask(BukkitService bukkitService, String name, String[] lines, int interval) {
this.bukkitService = bukkitService;
this.name = name;
this.msg = lines;
this.interval = interval;
}
public MessageTask(AuthMe plugin, String name, MessageKey messageKey, int interval) {
this(plugin, name, plugin.getMessages().retrieve(messageKey), interval);
/*
* Constructor.
*/
public MessageTask(BukkitService bukkitService, Messages messages, String name, MessageKey messageKey,
int interval) {
this(bukkitService, name, messages.retrieve(messageKey), interval);
}
@Override
@ -42,12 +41,12 @@ public class MessageTask implements Runnable {
return;
}
for (Player player : Utils.getOnlinePlayers()) {
for (Player player : bukkitService.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(name)) {
for (String ms : msg) {
player.sendMessage(ms);
}
BukkitTask nextTask = plugin.getServer().getScheduler().runTaskLater(plugin, this, interval * 20);
BukkitTask nextTask = bukkitService.runTaskLater(this, interval * 20);
if (LimboCache.getInstance().hasLimboPlayer(name)) {
LimboCache.getInstance().getLimboPlayer(name).setMessageTask(nextTask);
}

View File

@ -1,7 +1,18 @@
package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
/**
* Service for operations requiring server entities, such as for scheduling.
@ -14,9 +25,12 @@ public class BukkitService {
public static final int TICKS_PER_MINUTE = 60 * TICKS_PER_SECOND;
private final AuthMe authMe;
private final boolean getOnlinePlayersIsCollection;
private Method getOnlinePlayers;
public BukkitService(AuthMe authMe) {
this.authMe = authMe;
getOnlinePlayersIsCollection = initializeOnlinePlayersIsCollectionField();
}
/**
@ -44,6 +58,47 @@ public class BukkitService {
return Bukkit.getScheduler().scheduleSyncDelayedTask(authMe, task, delay);
}
/**
* Returns a task that will run on the next server tick.
*
* @param task the task to be run
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTask(Runnable task) {
return Bukkit.getScheduler().runTask(authMe, task);
}
/**
* Returns a task that will run after the specified number of server
* ticks.
*
* @param task the task to be run
* @param delay the ticks to wait before running the task
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTaskLater(Runnable task, long delay) {
return Bukkit.getScheduler().runTaskLater(authMe, task, delay);
}
/**
* <b>Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.</b>
* <p>
* Returns a task that will run asynchronously.
*
* @param task the task to be run
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTaskAsynchronously(Runnable task) {
return Bukkit.getScheduler().runTaskAsynchronously(authMe, task);
}
/**
* Broadcast a message to all players.
*
@ -54,4 +109,76 @@ public class BukkitService {
return Bukkit.broadcastMessage(message);
}
/**
* Gets the player with the exact given name, case insensitive.
*
* @param name Exact name of the player to retrieve
* @return a player object if one was found, null otherwise
*/
public Player getPlayerExact(String name) {
return authMe.getServer().getPlayerExact(name);
}
/**
* Gets a set containing all banned players.
*
* @return a set containing banned players
*/
public Set<OfflinePlayer> getBannedPlayers() {
return Bukkit.getBannedPlayers();
}
/**
* Safe way to retrieve the list of online players from the server. Depending on the
* implementation of the server, either an array of {@link Player} instances is being returned,
* or a Collection. Always use this wrapper to retrieve online players instead of {@link
* Bukkit#getOnlinePlayers()} directly.
*
* @return collection of online players
*
* @see <a href="https://www.spigotmc.org/threads/solved-cant-use-new-getonlineplayers.33061/">SpigotMC
* forum</a>
* @see <a href="http://stackoverflow.com/questions/32130851/player-changed-from-array-to-collection">StackOverflow</a>
*/
@SuppressWarnings("unchecked")
public Collection<? extends Player> getOnlinePlayers() {
if (getOnlinePlayersIsCollection) {
return Bukkit.getOnlinePlayers();
}
try {
// The lookup of a method via Reflections is rather expensive, so we keep a reference to it
if (getOnlinePlayers == null) {
getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
}
Object obj = getOnlinePlayers.invoke(null);
if (obj instanceof Collection<?>) {
return (Collection<? extends Player>) obj;
} else if (obj instanceof Player[]) {
return Arrays.asList((Player[]) obj);
} else {
String type = (obj != null) ? obj.getClass().getName() : "null";
ConsoleLogger.showError("Unknown list of online players of type " + type);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
ConsoleLogger.logException("Could not retrieve list of online players:", e);
}
return Collections.emptyList();
}
/**
* Method run upon initialization to verify whether or not the Bukkit implementation
* returns the online players as a Collection.
*
* @see #getOnlinePlayers()
*/
private static boolean initializeOnlinePlayersIsCollectionField() {
try {
Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
return method.getReturnType() == Collection.class;
} catch (NoSuchMethodException e) {
ConsoleLogger.showError("Error verifying if getOnlinePlayers is a collection! Method doesn't exist");
}
return false;
}
}

View File

@ -1,8 +1,8 @@
package fr.xephi.authme.util;
import com.maxmind.geoip.LookupService;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.Settings;
import java.io.File;
import java.io.FileOutputStream;
@ -37,7 +37,8 @@ public class GeoLiteAPI {
if (lookupService != null) {
return true;
}
final File data = new File(Settings.PLUGIN_FOLDER, "GeoIP.dat");
final File pluginFolder = AuthMe.getInstance().getDataFolder();
final File data = new File(pluginFolder, "GeoIP.dat");
boolean dataIsOld = (System.currentTimeMillis() - data.lastModified()) > TimeUnit.DAYS.toMillis(30);
if (dataIsOld && !data.delete()) {
ConsoleLogger.showError("Failed to delete GeoLiteAPI database");

View File

@ -37,12 +37,17 @@ public final class MigrationService {
if (HashAlgorithm.PLAINTEXT == settings.getProperty(SecuritySettings.PASSWORD_HASH)) {
ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated;"
+ " it will be changed and hashed now to the AuthMe default hashing method");
ConsoleLogger.showError("Don't stop your server; wait for the conversion to have been completed!");
List<PlayerAuth> allAuths = dataSource.getAllAuths();
for (PlayerAuth auth : allAuths) {
HashedPassword hashedPassword = authmeSha256.computeHash(
auth.getPassword().getHash(), auth.getNickname());
auth.setPassword(hashedPassword);
dataSource.updatePassword(auth);
String hash = auth.getPassword().getHash();
if (hash.startsWith("$SHA$")) {
ConsoleLogger.showError("Skipping conversion for " + auth.getNickname() + "; detected SHA hash");
} else {
HashedPassword hashedPassword = authmeSha256.computeHash(hash, auth.getNickname());
auth.setPassword(hashedPassword);
dataSource.updatePassword(auth);
}
}
settings.setProperty(SecuritySettings.PASSWORD_HASH, HashAlgorithm.SHA256);
settings.save();

View File

@ -7,41 +7,23 @@ import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.events.AuthMeTeleportEvent;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Utility class for various operations used in the codebase.
*/
public final class Utils {
private static AuthMe plugin;
private static Wrapper wrapper;
private static boolean getOnlinePlayersIsCollection = false;
private static Method getOnlinePlayers;
static {
wrapper = Wrapper.getInstance();
plugin = wrapper.getAuthMe();
initializeOnlinePlayersIsCollectionField();
}
private static AuthMe plugin = AuthMe.getInstance();
private Utils() {
// Utility class
}
/**
@ -170,12 +152,12 @@ public final class Utils {
final World world = theWorld;
final Location loc = new Location(world, x, y, z);
Bukkit.getScheduler().scheduleSyncDelayedTask(wrapper.getAuthMe(), new Runnable() {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(pl, loc);
wrapper.getServer().getPluginManager().callEvent(tpEvent);
plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
pl.teleport(tpEvent.getTo());
}
@ -183,62 +165,6 @@ public final class Utils {
});
}
/**
* Safe way to retrieve the list of online players from the server. Depending on the
* implementation of the server, either an array of {@link Player} instances is being returned,
* or a Collection. Always use this wrapper to retrieve online players instead of {@link
* Bukkit#getOnlinePlayers()} directly.
*
* @return collection of online players
*
* @see <a href="https://www.spigotmc.org/threads/solved-cant-use-new-getonlineplayers.33061/">SpigotMC
* forum</a>
* @see <a href="http://stackoverflow.com/questions/32130851/player-changed-from-array-to-collection">StackOverflow</a>
*/
@SuppressWarnings("unchecked")
public static Collection<? extends Player> getOnlinePlayers() {
if (getOnlinePlayersIsCollection) {
return Bukkit.getOnlinePlayers();
}
try {
// The lookup of a method via Reflections is rather expensive, so we keep a reference to it
if (getOnlinePlayers == null) {
getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
}
Object obj = getOnlinePlayers.invoke(null);
if (obj instanceof Collection<?>) {
return (Collection<? extends Player>) obj;
} else if (obj instanceof Player[]) {
return Arrays.asList((Player[]) obj);
} else {
String type = (obj != null) ? obj.getClass().getName() : "null";
ConsoleLogger.showError("Unknown list of online players of type " + type);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
ConsoleLogger.logException("Could not retrieve list of online players:", e);
}
return Collections.emptyList();
}
/**
* Method run when the Utils class is loaded to verify whether or not the Bukkit implementation
* returns the online players as a Collection.
*
* @see Utils#getOnlinePlayers()
*/
private static void initializeOnlinePlayersIsCollectionField() {
try {
Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
getOnlinePlayersIsCollection = method.getReturnType() == Collection.class;
} catch (NoSuchMethodException e) {
ConsoleLogger.showError("Error verifying if getOnlinePlayers is a collection! Method doesn't exist");
}
}
public static Player getPlayer(String name) {
return wrapper.getServer().getPlayerExact(name);
}
public static boolean isNPC(Player player) {
return player.hasMetadata("NPC") || plugin.getPluginHooks().isNpcInCombatTagPlus(player);
}
@ -247,45 +173,19 @@ public final class Utils {
if (Settings.isTeleportToSpawnEnabled && !Settings.noTeleport) {
Location spawn = plugin.getSpawnLocation(player);
AuthMeTeleportEvent tpEvent = new AuthMeTeleportEvent(player, spawn);
wrapper.getServer().getPluginManager().callEvent(tpEvent);
plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) {
player.teleport(tpEvent.getTo());
}
}
}
public static boolean isEmailCorrect(String email, NewSetting settings) {
if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) {
return false;
}
final String emailDomain = email.split("@")[1];
List<String> whitelist = settings.getProperty(EmailSettings.DOMAIN_WHITELIST);
if (!CollectionUtils.isEmpty(whitelist)) {
return containsIgnoreCase(whitelist, emailDomain);
}
List<String> blacklist = settings.getProperty(EmailSettings.DOMAIN_BLACKLIST);
return CollectionUtils.isEmpty(blacklist) || !containsIgnoreCase(blacklist, emailDomain);
}
private static boolean containsIgnoreCase(Collection<String> coll, String needle) {
for (String entry : coll) {
if (entry.equalsIgnoreCase(needle)) {
return true;
}
}
return false;
}
public static String getUUIDorName(OfflinePlayer player) {
String uuidOrName;
try {
uuidOrName = player.getUniqueId().toString();
return player.getUniqueId().toString();
} catch (Exception ignore) {
uuidOrName = player.getName();
return player.getName();
}
return uuidOrName;
}
public enum GroupType {
@ -294,4 +194,15 @@ public final class Utils {
NOTLOGGEDIN,
LOGGEDIN
}
/**
* Returns the IP of the given player.
*
* @param p The player to return the IP address for
*
* @return The player's IP address
*/
public static String getPlayerIp(Player p) {
return p.getAddress().getAddress().getHostAddress();
}
}

View File

@ -0,0 +1,133 @@
package fr.xephi.authme.util;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.CommandSender;
import java.util.Collection;
import java.util.List;
/**
* Validation service.
*/
public class ValidationService {
private final NewSetting settings;
private final DataSource dataSource;
private final PermissionsManager permissionsManager;
public ValidationService(NewSetting settings, DataSource dataSource, PermissionsManager permissionsManager) {
this.settings = settings;
this.dataSource = dataSource;
this.permissionsManager = permissionsManager;
}
/**
* Verifies whether a password is valid according to the plugin settings.
*
* @param password the password to verify
* @param username the username the password is associated with
* @return message key with the password error, or {@code null} if password is valid
*/
public MessageKey validatePassword(String password, String username) {
String passLow = password.toLowerCase();
if (!passLow.matches(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
return MessageKey.PASSWORD_MATCH_ERROR;
} else if (passLow.equalsIgnoreCase(username)) {
return MessageKey.PASSWORD_IS_USERNAME_ERROR;
} else if (password.length() < settings.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|| password.length() > settings.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
return MessageKey.INVALID_PASSWORD_LENGTH;
} else if (settings.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(passLow)) {
// TODO #602 20160312: The UNSAFE_PASSWORDS should be all lowercase
// -> introduce a lowercase String list property type
return MessageKey.PASSWORD_UNSAFE_ERROR;
}
return null;
}
/**
* Verifies whether the email is valid and admitted for use according to the plugin settings.
*
* @param email the email to verify
* @return true if the email is valid, false otherwise
*/
public boolean validateEmail(String email) {
if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) {
return false;
}
final String emailDomain = email.split("@")[1];
return validateWhitelistAndBlacklist(
emailDomain, EmailSettings.DOMAIN_WHITELIST, EmailSettings.DOMAIN_BLACKLIST);
}
/**
* Queries the database whether the email is still free for registration, i.e. whether the given
* command sender may use the email to register a new account (as defined by settings and permissions).
*
* @param email the email to verify
* @param sender the command sender
* @return true if the email may be used, false otherwise (registration threshold has been exceeded)
*/
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
return permissionsManager.hasPermission(sender, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
|| dataSource.countAuthsByEmail(email) < settings.getProperty(EmailSettings.MAX_REG_PER_EMAIL);
}
/**
* Checks whether the player's country is allowed to join the server, based on the given IP address
* and the configured country whitelist or blacklist.
*
* @param hostAddress the IP address to verify
* @return true if the IP address' country is allowed, false otherwise
*/
public boolean isCountryAdmitted(String hostAddress) {
// Check if we have restrictions on country, if not return true and avoid the country lookup
if (settings.getProperty(ProtectionSettings.COUNTRIES_WHITELIST).isEmpty()
&& settings.getProperty(ProtectionSettings.COUNTRIES_BLACKLIST).isEmpty()) {
return true;
}
String countryCode = GeoLiteAPI.getCountryCode(hostAddress);
return validateWhitelistAndBlacklist(countryCode,
ProtectionSettings.COUNTRIES_WHITELIST,
ProtectionSettings.COUNTRIES_BLACKLIST);
}
/**
* Verifies whether the given value is allowed according to the given whitelist and blacklist settings.
* Whitelist has precedence over blacklist: if a whitelist is set, the value is rejected if not present
* in the whitelist.
*
* @param value the value to verify
* @param whitelist the whitelist property
* @param blacklist the blacklist property
* @return true if the value is admitted by the lists, false otherwise
*/
private boolean validateWhitelistAndBlacklist(String value, Property<List<String>> whitelist,
Property<List<String>> blacklist) {
List<String> whitelistValue = settings.getProperty(whitelist);
if (!CollectionUtils.isEmpty(whitelistValue)) {
return containsIgnoreCase(whitelistValue, value);
}
List<String> blacklistValue = settings.getProperty(blacklist);
return CollectionUtils.isEmpty(blacklistValue) || !containsIgnoreCase(blacklistValue, value);
}
private static boolean containsIgnoreCase(Collection<String> coll, String needle) {
for (String entry : coll) {
if (entry.equalsIgnoreCase(needle)) {
return true;
}
}
return false;
}
}

View File

@ -1,74 +0,0 @@
package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.output.Messages;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.scheduler.BukkitScheduler;
import java.io.File;
/**
* Wrapper for the retrieval of common singletons used throughout the application.
* This class simply delegates the calls.
*/
public class Wrapper {
private static Wrapper singleton;
/**
* Package-private constructor for testing purposes to inject a mock instance.
*/
Wrapper() {
}
/**
* Package-private setter of the singleton field used for tests to inject a mock instance.
*
* @param wrapper The wrapper to use as singleton
*/
static void setSingleton(Wrapper wrapper) {
Wrapper.singleton = wrapper;
}
public static Wrapper getInstance() {
if (singleton == null) {
singleton = new Wrapper();
}
return singleton;
}
public AuthMe getAuthMe() {
return AuthMe.getInstance();
}
public Server getServer() {
return getAuthMe().getServer();
}
public Messages getMessages() {
return getAuthMe().getMessages();
}
public PlayerCache getPlayerCache() {
return PlayerCache.getInstance();
}
/**
* Return the folder containing plugin data via the AuthMe instance.
*
* @return The plugin data folder
* @see AuthMe#getDataFolder()
*/
public File getDataFolder() {
return getAuthMe().getDataFolder();
}
public BukkitScheduler getScheduler() {
return Bukkit.getScheduler();
}
}

View File

@ -67,6 +67,8 @@ settings:
# Care that this feature blocks also all the commands not
# listed in the list below.
allowChat: false
# Can not authenticated players see the chat log?
hideChat: false
# WARNING: use this only if you need it!
# Allow unlogged users to use all the commands if registration is not forced!
allowAllCommandsIfRegistrationIsOptional: false
@ -159,6 +161,9 @@ settings:
noTeleport: false
# Regex syntax for allowed Chars in passwords.
allowedPasswordCharacters: '[\x21-\x7E]*'
# Keeps collisions disabled for logged players
# Works only with MC 1.9
keepCollisionsDisabled: false
GameMode:
# ForceSurvivalMode to player when join ?
ForceSurvivalMode: false
@ -248,11 +253,11 @@ settings:
forceRegisterCommands: []
# Force these commands after /register as a server console, without any '/', use %p for replace with player name
forceRegisterCommandsAsConsole: []
# Do we need to display the welcome message (welcome.txt) after a register or a login?
# You can use colors in this welcome.txt + some replaced strings :
# {PLAYER} : player name, {ONLINE} : display number of online players, {MAXPLAYERS} : display server slots,
# {IP} : player ip, {LOGINS} : number of players logged, {WORLD} : player current world, {SERVER} : server name
# {VERSION} : get current bukkit version, {COUNTRY} : player country
# Do we need to display the welcome message (welcome.txt) after a login?
# You can use colors in this welcome.txt + some replaced strings:
# {PLAYER}: player name, {ONLINE}: display number of online players, {MAXPLAYERS}: display server slots,
# {IP}: player ip, {LOGINS}: number of players logged, {WORLD}: player current world, {SERVER}: server name
# {VERSION}: get current bukkit version, {COUNTRY}: player country
useWelcomeMessage: true
# Do we need to broadcast the welcome message to all server or only to the player? set true for server or false for player
broadcastWelcomeMessage: false
@ -418,6 +423,3 @@ Protection:
antiBotSensibility: 5
# Duration in minutes of the antibot automatic system
antiBotDuration: 10
VeryGames:
# These features are only available on VeryGames Server Provider
enableIpCheck: false

View File

@ -1,30 +1,30 @@
unknown_user: '&cBenutzer ist nicht in der Datenbank'
unsafe_spawn: '&cDeine Logoutposition war unsicher, Du wurdest zum Spawn teleportiert'
unsafe_spawn: '&cDeine Logoutposition war unsicher, du wurdest zum Spawn teleportiert'
not_logged_in: '&cNicht eingeloggt!'
reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren "/register <passwort> <passwortBestätigen>"'
reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren: "/register <passwort> <passwortBestätigen>"'
usage_log: '&cBenutze: /login <passwort>'
wrong_pwd: '&cFalsches Passwort'
unregistered: '&cBenutzerkonto erfolgreich gelöscht!'
reg_disabled: '&cRegistrierungen sind deaktiviert'
valid_session: '&2Erfolgreich eingeloggt!'
login: '&2Erfolgreich eingeloggt!'
vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe Deine E-Mails!'
vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe deine E-Mails!'
user_regged: '&cDieser Benutzername ist schon vergeben'
usage_reg: '&cBenutze: /register <passwort> <passwortBestätigen>'
max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht.'
max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht (%max_acc/%reg_count).'
no_perm: '&4Du hast keine Rechte, um diese Aktion auszuführen!'
error: '&4Ein Fehler ist aufgetreten. Bitte kontaktiere einen Administrator.'
login_msg: '&cBitte logge Dich ein mit "/login <passwort>"'
reg_msg: '&3Bitte registriere Dich mit "/register <passwort> <passwortBestätigen>"'
reg_email_msg: '&3Bitte registriere Dich mit "/register <email> <emailBestätigen>"'
login_msg: '&cBitte logge dich ein mit "/login <passwort>"'
reg_msg: '&3Bitte registriere dich mit "/register <passwort> <passwortBestätigen>"'
reg_email_msg: '&3Bitte registriere dich mit "/register <email> <emailBestätigen>"'
usage_unreg: '&cBenutze: /unregister <passwort>'
pwd_changed: '&2Passwort geändert!'
user_unknown: '&cBenutzername nicht registriert!'
password_error: '&cPasswörter stimmen nicht überein!'
password_error_nick: '&cDu kannst nicht Deinen Namen als Passwort nutzen!'
password_error_unsafe: '&cDu kannst nicht unsichere Passwörter nutzen!'
invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist'
reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com zum Registrieren'
password_error_nick: '&cDu kannst deinen Namen nicht als Passwort verwenden!'
password_error_unsafe: '&cPasswort unsicher! Bitte wähle ein anderes.'
invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist.'
reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com um dich zu registrieren.'
logged_in: '&cBereits eingeloggt!'
logout: '&2Erfolgreich ausgeloggt'
same_nick: '&4Jemand mit diesem Namen spielt bereits auf dem Server!'
@ -34,8 +34,8 @@ reload: '&2Konfiguration und Datenbank wurden erfolgreich neu geladen.'
timeout: '&4Zeitüberschreitung beim Login'
usage_changepassword: '&cBenutze: /changepassword <altesPasswort> <neuesPasswort>'
name_len: '&4Dein Nickname ist zu kurz oder zu lang.'
regex: '&4Dein Nickname enthält nicht erlaubte Zeichen. Zulässige Zeichen: REG_EX'
add_email: '&3Bitte hinterlege Deine E-Mail-Adresse: /email add <deineEmail> <emailBestätigen>'
regex: '&4Dein Nickname enthält unerlaubte Zeichen. Zulässige Zeichen: REG_EX'
add_email: '&3Bitte hinterlege deine E-Mail-Adresse: /email add <deineEmail> <emailBestätigen>'
recovery_email: '&3Passwort vergessen? Nutze "/email recovery <deineEmail>" für ein neues Passwort'
usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha <theCaptcha>'
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
@ -49,14 +49,14 @@ new_email_invalid: '&cDie neue E-Mail ist ungültig!'
old_email_invalid: '&cDie alte E-Mail ist ungültig!'
email_invalid: '&cUngültige E-Mail!'
email_added: '&2E-Mail hinzugefügt!'
email_confirm: '&cBitte bestätige Deine E-Mail!'
email_confirm: '&cBitte bestätige deine E-Mail!'
email_changed: '&2E-Mail aktualisiert!'
email_send: '&2Wiederherstellungs-E-Mail wurde gesendet!'
email_exists: '&cEine Wiederherstellungs-E-Mail wurde bereits versandt! Nutze folgenden Befehl um eine neue E-Mail zu versenden:'
country_banned: '&4Dein Land ist gesperrt!'
antibot_auto_enabled: '&4[AntiBotService] AntiBotMod wurde aufgrund hoher Netzauslastung automatisch aktiviert!'
antibot_auto_disabled: '&2[AntiBotService] AntiBotMod wurde nach %m Minuten deaktiviert, hoffentlich ist die Invasion vorbei.'
kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor Du Dich mit dem Server verbindest.'
kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor du dich mit dem Server verbindest.'
two_factor_create: '&2Dein geheimer Code ist %code. Du kannst ihn hier abfragen: %url'
email_already_used: '&4Diese E-Mail-Adresse wird bereits genutzt.'
invalid_name_case: 'Dein registrierter Benutzername ist &2%valid&f - nicht &4%invalid&f.'

View File

@ -1,50 +1,50 @@
reg_only: Csak regisztrált játékosoknak! Jelentkezni a mail@email.com e-mail címen lehet
usage_unreg: '&cHasználat: /unregister jelszó'
registered: '&aSikeres regisztráció. Üdvözöllek!'
user_regged: '&cJátékosnév már regisztrálva'
login_msg: '&cKérlek jelentkezz be: "/login jelszó"'
reg_only: '&4Csak regisztrált játékosok tudnak csatlakozni a szerverhez! Kérlek kattints a http://example.com weboldalra és regisztráld magad!'
usage_unreg: '&cHasználat: "/unregister <jelszó>"'
registered: '&aSikeres regisztráció.'
user_regged: '&cEz a játékosnév már regisztrálva van!'
login_msg: '&cKérlek jelentkezz be: "/login <jelszó>"'
not_logged_in: '&cNem vagy bejelentkezve!'
logout: '&cSikeresen kijelentkeztél!'
usage_log: '&cBejelentkezés: /login <jelszó>'
unknown_user: '&cA kért felhasználó nem telálható az adatbázisban!'
reg_voluntarily: Regisztrálhatod magad a szerveren a következö parancsal "/register <jelszó> <jelszó újra>"
usage_log: '&cBejelentkezés: "/login <jelszó>"'
unknown_user: '&cA kért felhasználó nem található az adatbázisban!'
reg_voluntarily: Regisztrálhatod magad a szerveren a következö parancsal "/register <jelszó> <jelszó ismét>"
reg_disabled: '&cRegisztráció letiltva!'
no_perm: '&cNincs jogod ehhez!'
usage_reg: '&cHasználat: /register <jelszó> <jelszó újra>'
usage_reg: '&cHasználat: "/register <jelszó> <jelszó ismét>"'
password_error_nick: '&cNem használhatod a felhasználóneved jelszónak, kérlek válassz másikat...'
password_error_unsafe: '&cA választott jelszó nem biztonságos, kérlek válassz másikat...'
unregistered: '&cRegisztráció sikeresen törölve!'
same_nick: 'Ezzel a játékosnévvel már játszanak a szerveren.'
valid_session: '&2A hálózati kapcsolat újraépítése megtörtént.'
valid_session: '&2A megadott időkereten belül csatlakoztál vissza így a rendszer automatikusan beléptetett.'
pwd_changed: '&cJelszó cserélve!'
reload: 'Beálítások és adatbázis újratöltve!'
timeout: 'Bejelentkezési időtúllépés!'
error: 'Hiba lépett fel; Lépj kapcsolatba a tulajjal'
error: 'Hiba lépett fel! Lépj kapcsolatba a tulajjal!'
logged_in: '&cMár be vagy jelentkezve!'
login: '&aSikeresen beléptél!'
wrong_pwd: '&4Hibás jelszó!'
user_unknown: '&cEz a felhasználó nincs regisztrálva!'
reg_msg: '&cKérlek Regisztrálj: "/register jelszó jelszóújra"'
reg_msg: '&cKérlek Regisztrálj: "/register <jelszó> <jelszó ismét>"'
reg_email_msg: '&cKérlek regisztrálj: "/register <Email> <Email újra>"'
unsafe_spawn: 'A kilépési helyzeted nem biztonságos, teleportálás a Spawnra.'
max_reg: 'Csak egy karakterrel registrálhatsz!'
unsafe_spawn: 'A kilépési helyzeted nem biztonságos, teleportálás a kezdő pozícióra.'
max_reg: '&cElérted a maximálisan beregisztrálható karakterek számát. (%reg_count/%max_acc %reg_names)!'
password_error: 'A két jelszó nem egyezik!'
invalid_session: '&cAz IP címed megváltozott és a hálózati kapcsolatod lejárt. Kapcsolódj újra.'
invalid_session: '&cAz IP címed megváltozott, ezért a visszacsatlakozási időkereted lejárt.'
pass_len: 'A jelszavad nem éri el a minimális hosszúságot!'
vb_nonActiv: '&cA felhasználód aktiválása még nem történt meg, ellenőrizd a leveleid!'
usage_changepassword: 'Használat: /changepassword <régi Jelszó> <új Jelszó>'
vb_nonActiv: '&cA felhasználód aktiválása még nem történt meg, ellenőrizd a megadott emailed!'
usage_changepassword: 'Használat: "/changepassword <régi Jelszó> <új Jelszó>"'
name_len: '&4A felhasználó neved túl hosszú, vagy túl rövid! Válassz másikat!'
regex: '&4A felhasználóneved nem használható karaktereket tartalmaz. Elfogadott karakterek: REG_EX'
add_email: '&3Kérlek add hozzá a felhasználódhoz az email címedet "/email add <Email címed> <Email címed ismét>"'
recovery_email: '&3Ha elfelejtetted a jelszavad, használd az: "/email recovery <regisztrált Email címed>"'
usage_captcha: '&3A bejelentkezéshez CAPTCHA szükséges, kérem használd a következő parancsot "/captcha <theCaptcha>"'
wrong_captcha: '&cHibás captcha, kérlek írd be a következő parancsot "/captcha THE_CAPTCHA" a chat-be!'
valid_captcha: '&2Captcha sikeresen feloldva!'
usage_captcha: '&3A bejelentkezéshez CAPTCHA szükséges, kérlek használd a következő parancsot "/captcha <theCaptcha>"'
wrong_captcha: '&cHibás CAPTCHA, kérlek írd be a következő parancsot "/captcha THE_CAPTCHA"!'
valid_captcha: '&2CAPTCHA sikeresen feloldva!'
kick_forvip: '&3VIP játékos csatlakozott a szerverhez!'
kick_fullserver: '&4A szerver megtelt, próbálj csatlakozni később!'
usage_email_add: '&cHasználat: /email add <email> <Email újra>'
usage_email_change: '&cHasználat: /email change <régi Email> <új Email>'
usage_email_recovery: '&cHasználat: /email recovery <email>'
usage_email_add: '&cHasználat: "/email add <email> <Email újra>"'
usage_email_change: '&cHasználat: "/email change <régi Email> <új Email>"'
usage_email_recovery: '&cHasználat: "/email recovery <email>"'
new_email_invalid: '&cHibás az új email cím, próbáld újra!'
old_email_invalid: '&cHibás a régi email cím, próbáld újra!'
email_invalid: '&cHibás az email cím, próbáld újra!'
@ -52,12 +52,12 @@ email_added: '&2Az email címed rögzítése sikeresen megtörtént!'
email_confirm: '&cKérlek ellenőrízd az email címedet!'
email_changed: '&2Az email cím cseréje sikeresen megtörtént!'
email_send: '&2A jelszó visszaállításhoz szükséges emailt elküldtük! Ellenőrízd a leveleidet!'
email_exists: '&cA visszaállító emailt elküldtük! Hiba esetén újkérheted az alábbi parancs segítségével:'
email_exists: '&cA visszaállító emailt elküldtük! Hiba esetén újra kérheted az alábbi parancs segítségével:'
email_already_used: '&4Ez az email cím már használatban van!'
country_banned: '&4Az országod tiltólistán van ezen a szerveren!'
antibot_auto_enabled: '&4[AntiBot] Az AntiBot védelem bekapcsolt a nagy számú hálózati kapcsolat miatt!'
antibot_auto_disabled: '&2[AntiBot] Az AntiBot kikapcsol %m múlva!'
kick_antibot: 'Az AntiBot védelem bekapcsolva! Kérünk várj pár másodpercet a csatlakozáshoz.'
# TODO email_already_used: '&4The email address is already being used'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
antibot_auto_enabled: '&4[AntiBot] Az AntiBot védelem bekapcsolt, mert a megszabott időn belül több felhasználó csatlakozott!'
antibot_auto_disabled: '&2[AntiBot] Az AntiBot kikapcsol %m perc múlva!'
kick_antibot: 'Az AntiBot védelem bekapcsolva! Kérlek várj pár percet mielőtt csatlakozol.'
not_owner_error: 'Ez nem a te felhasználód. Kérlek válassz másik nevet!'
invalid_name_case: '%valid a felhasználó neved nem? Akkor ne %invalid névvel próbálj feljönni.'
two_factor_create: '&2A te titkos kódod a következő: %code. Vagy skenneld be a következő oldalról: %url'

View File

@ -1,64 +1,64 @@
#Lingua Italiana creata da Maxetto e sgdc3.
unknown_user: 'L''utente non è presente nel database.'
unsafe_spawn: 'Il tuo punto di disconnessione risulta ostruito o insicuro, sei stato teletrasportato al punto di rigenerazione!'
# Lingua Italiana creata da Maxetto e sgdc3.
kick_antibot: 'Il servizio di AntiBot è attualmente attivo! Devi aspettare qualche minuto prima di poter entrare nel server.'
unknown_user: '&cL''utente non è presente nel database.'
unsafe_spawn: '&cIl tuo punto di disconnessione risulta ostruito o insicuro, sei stato teletrasportato al punto di rigenerazione!'
not_logged_in: '&cNon hai ancora eseguito l''autenticazione!'
reg_voluntarily: 'Puoi eseguire la registrazione al server con il comando: "/register <password> <confermaPassword>"'
usage_log: '&cUtilizzo: /login <password>'
wrong_pwd: '&cPassword non corretta!'
unregistered: '&cSei stato rimosso dal database con successo!'
unregistered: '&2Sei stato correttamente rimosso dal database!'
reg_disabled: '&cLa registrazione tramite i comandi di gioco è disabilitata.'
valid_session: '&cAutenticato automaticamente attraverso la precedente sessione!'
login: '&cAutenticazone effettuata correttamente!'
vb_nonActiv: 'Il tuo account non è stato ancora verificato, controlla fra le tue email per scoprire come attivarlo!'
valid_session: '&2Autenticato automaticamente attraverso la precedente sessione!'
login: '&2Autenticazone effettuata correttamente!'
vb_nonActiv: '&cIl tuo account non è stato ancora verificato, controlla fra le tue email per scoprire come attivarlo!'
user_regged: '&cHai già effettuato la registrazione, non puoi eseguirla nuovamente.'
usage_reg: '&cUtilizzo: /register <password> <confermaPassword>'
error: 'Qualcosa è andato storto, riporta questo errore ad un Admin!'
max_reg: 'Hai raggiunto il numero massimo di registrazioni per questo indirizzo IP!'
no_perm: '&cNon hai il permesso di eseguire questa operazione.'
login_msg: '&cPerfavore, esegui l''autenticazione con il comando: "/login <password>"'
reg_msg: '&cPerfavore, esegui la registrazione con il comando: "/register <password> <confermaPassword>"'
reg_email_msg: '&cPerfavore, esegui la registrazione con il comando: "/register <email> <confermaEmail>"'
max_reg: '&cHai raggiunto il numero massimo di registrazioni (%reg_count/%max_acc %reg_names) per questo indirizzo IP!'
no_perm: '&4Non hai il permesso di eseguire questa operazione.'
error: '&4Qualcosa è andato storto, riporta questo errore ad un Admin!'
login_msg: '&cPer favore, esegui l''autenticazione con il comando: "/login <password>"'
reg_msg: '&3Per favore, esegui la registrazione con il comando: "/register <password> <confermaPassword>"'
reg_email_msg: '&3Per favore, esegui la registrazione con il comando: "/register <email> <confermaEmail>"'
usage_unreg: '&cUtilizzo: /unregister <password>'
pwd_changed: '&cPassword cambiata con successo!'
pwd_changed: '&2Password cambiata correttamente!'
user_unknown: '&cL''utente non ha ancora eseguito la registrazione.'
password_error: 'Le Password non corrispondono!'
password_error_nick: 'Non puoi usare il tuo nome utente come password, scegline un''altra!'
password_error_unsafe: 'La password che hai inserito non è sicura, scegline un''altra!'
invalid_session: 'I tuoi dati di connessione attuali non sono quelli utilizzati in precedenza. Attendi la fine della sessione attuale.'
reg_only: 'Puoi giocare in questo server solo dopo aver effettuato la registrazione attraverso il sito web! Perfavore, vai su http://esempio.it per procedere!'
logged_in: '&cHai già eseguito l''autenticazione, non devi eseguirla nuovamente!'
logout: '&cDisconnessione avvenuta correttamente!'
same_nick: 'Questo stesso nome utente è già online sul server!'
registered: '&cRegistrato correttamente!'
pass_len: 'La password che hai inserito è troppo corta o troppo lunga, scegline un''altra!'
reload: 'La configurazione e il database sono stati ricaricati con successo!'
timeout: 'Tempo scaduto per effettuare l''autenticazione'
usage_changepassword: 'Utilizzo: /changepassword <vecchiaPassword> <nuovaPassword>'
name_len: '&cIl tuo nome utente è troppo corto o troppo lungo!'
regex: '&cIl tuo nome utente contiene caratteri non consentiti. I caratteri consentiti sono: REG_EX'
add_email: '&cPer poter recuperare la password in futuro, aggiungi un indirizzo email al tuo account con il comando: "/email add <tuaEmail> <confermaEmail>"'
recovery_email: '&cHai dimenticato la tua password? Puoi recuperarla eseguendo il comando: "/email recovery <tuaEmail>"'
usage_captcha: '&cAbbiamo bisogno che tu inserisca un captcha, perfavore scrivi: "/captcha <theCaptcha>"'
wrong_captcha: '&cCaptcha sbagliato, perfavore riprova con il comando: "/captcha THE_CAPTCHA"'
valid_captcha: '&cIl captcha inserito è valido!'
kick_forvip: '&cUn utente VIP è entrato mentre il server era pieno e ha preso il tuo posto!'
kick_fullserver: '&cIl server è attualmente pieno, riprova più tardi!'
usage_email_add: '&fUtilizzo: /email add <email> <confermaEmail>'
usage_email_change: '&fUtilizzo: /email change <vecchiaEmail> <nuovaEmail>'
usage_email_recovery: '&fUtilizzo: /email recovery <email>'
new_email_invalid: 'Il nuovo indirizzo email inserito non è valido!'
old_email_invalid: 'Il vecchio indirizzo email inserito non è valido!'
email_invalid: 'L''indirizzo email inserito non è valido'
email_added: 'Indirizzo email aggiunto correttamente!'
email_confirm: 'Conferma il tuo indirizzo email!'
email_changed: 'Indirizzo email cambiato correttamente!'
email_send: 'Una email di recupero è stata appena inviata al tuo indirizzo email!'
email_exists: 'Il tuo account ha già un''indirizzo email configurato. Se vuoi, puoi cambiarlo con il seguente comando:'
country_banned: 'Il tuo paese è bandito da questo server!'
antibot_auto_enabled: 'Il servizio di AntiBot è stato automaticamente abilitato a seguito delle numerose connessioni!'
antibot_auto_disabled: "Il servizio di AntiBot è stato automaticamente disabilitato dopo %m Minuti, sperando che l'attacco sia finito!"
kick_antibot: 'Il servizio di AntiBot è attualmente attivo! Devi aspettare qualche minuto prima di poter entrare nel server.'
password_error: '&cLe password non corrispondono!'
password_error_nick: '&cNon puoi usare il tuo nome utente come password, per favore scegline un''altra...'
password_error_unsafe: '&cLa password che hai inserito non è sicura, per favore scegline un''altra...'
invalid_session: '&cIl tuo indirizzo IP è cambiato e la tua sessione è stata terminata!'
reg_only: '&4Puoi giocare in questo server solo dopo aver effettuato la registrazione attraverso il sito web! Per favore, vai su http://esempio.it per procedere!'
logged_in: '&cHai già eseguito l''autenticazione, non è necessario eseguirla nuovamente!'
logout: '&2Disconnessione avvenuta correttamente!'
same_nick: '&4Questo stesso nome utente è già online sul server!'
registered: '&2Registrato correttamente!'
pass_len: '&cLa password che hai inserito è troppo corta o troppo lunga, per favore scegline un''altra...'
reload: '&2La configurazione e il database sono stati ricaricati correttamente!'
timeout: '&4Tempo scaduto per effettuare l''autenticazione, sei stato espulso dal server, per favore riprova!'
usage_changepassword: '&cUtilizzo: /changepassword <vecchiaPassword> <nuovaPassword>'
name_len: '&4Il tuo nome utente è troppo corto o troppo lungo!'
regex: '&4Il tuo nome utente contiene caratteri non consentiti. I caratteri consentiti sono: REG_EX'
add_email: '&3Per poter recuperare la password in futuro, aggiungi un indirizzo email al tuo account con il comando: "/email add <tuaEmail> <confermaEmail>"'
recovery_email: '&3Hai dimenticato la tua password? Puoi recuperarla eseguendo il comando: "/email recovery <tuaEmail>"'
usage_captcha: '&3Per poterti autenticare devi risolvere un captcha, per favore scrivi: "/captcha <theCaptcha>"'
wrong_captcha: '&cCaptcha sbagliato, per favore riprova scrivendo: "/captcha THE_CAPTCHA" in chat!'
valid_captcha: '&2Il captcha inserito è valido!'
kick_forvip: '&3Un utente VIP è entrato mentre il server era pieno e ha preso il tuo posto!'
kick_fullserver: '&4Il server è attualmente pieno, riprova più tardi!'
usage_email_add: '&cUtilizzo: /email add <email> <confermaEmail>'
usage_email_change: '&cUtilizzo: /email change <vecchiaEmail> <nuovaEmail>'
usage_email_recovery: '&cUtilizzo: /email recovery <email>'
new_email_invalid: '&cIl nuovo indirizzo email inserito non è valido, riprova!'
old_email_invalid: '&cIl vecchio indirizzo email inserito non è valido, riprova!'
email_invalid: '&cL''indirizzo email inserito non è valido, riprova!'
email_added: '&2Indirizzo email aggiunto correttamente al tuo account!'
email_confirm: '&cPer favore, conferma il tuo indirizzo email!'
email_changed: '&2Indirizzo email cambiato correttamente!'
email_send: '&2Una email di recupero è stata appena inviata al tuo indirizzo email!'
email_exists: '&cUna email di recupero è già stata inviata! Se vuoi, puoi annullarla e mandarne un''altra con il seguente comando:'
country_banned: '&4Il tuo paese è bandito da questo server!'
antibot_auto_enabled: '&4Il servizio di AntiBot è stato automaticamente abilitato a seguito delle numerose connessioni!'
antibot_auto_disabled: "&2Il servizio di AntiBot è stato automaticamente disabilitato dopo %m Minuti, sperando che l'attacco sia finito!"
email_already_used: '&4L''indirizzo email inserito è già in uso'
two_factor_create: '&2Il tuo codice segreto è: &f%code&n&2Puoi anche scannerizzare il codice QR da qui: &f%url'
# TODO email_already_used: '&4The email address is already being used'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
not_owner_error: 'Non sei il proprietario di questo account. Per favore scegli un altro nome!'
invalid_name_case: 'Dovresti entrare con questo nome utente: "%valid", al posto di: "%invalid".'

View File

@ -1,68 +1,66 @@
# Translator: uSoc_lifehome (http://lifeho.me) #
# Translator: WaterXCubic 水方塊 #
# Translator: Unknown #
# Last modif: 1459528742 UTC #
# -------------------------------------------- #
unknown_user: '&8[&6用戶系統&8] &f用戶資料並不存在於資料庫中。'
unsafe_spawn: '&8[&6用戶系統&8] &f你的登出位置不安全現在將傳送你到重生點。'
not_logged_in: '&8[&6用戶系統&8] &c你還沒有登入 '
reg_voluntarily: '&8[&6用戶系統&8] &f你可以使用這個的指令來註冊 《 /register <密碼> <重覆密碼> 》'
usage_log: '&8[&6用戶系統&8] &c用法 《 /login <密碼> 》'
wrong_pwd: '&8[&6用戶系統&8] &c你輸入了錯誤的密碼。'
unregistered: '&8[&6用戶系統&8] &c你已成功取消會員註冊記錄。'
reg_disabled: '&8[&6用戶系統&8] &c本伺服器已停止新玩家註冊。'
valid_session: '&8[&6用戶系統&8] &b嗨 我記得你,歡迎回來~'
login: '&8[&6用戶系統&8] &c你成功的登入了。'
password_error_nick: '&f你不可以使用你的名字為密碼!'
password_error_unsafe: '&f你不可以使用不安全的密碼'
vb_nonActiv: '&8[&6用戶系統&8] &f你的帳戶還沒有經過電郵驗證 '
user_regged: '&8[&6用戶系統&8] &c此用戶名已經註冊過了。'
usage_reg: '&8[&6用戶系統&8] &c用法 《 /register <密碼> <重覆密碼> 》'
max_reg: '&8[&6用戶系統&8] &f你的IP地址已達到註冊數上限。'
no_perm: '&8[&6用戶系統&8] &b你可以到 CraftingHK 玩家百科中查看說明文件。'
error: '&8[&6用戶系統&8] &f發生錯誤請與管理員聯絡。'
login_msg: '&8[&6用戶系統&8] &c請使用這個指令來登入 《 /login <密碼> 》'
reg_msg: '&8[&6用戶系統&8] &c請使用這個的指令來註冊 《 /register <密碼> <重覆密碼> 》'
reg_email_msg: '&8[&6用戶系統&8] &c請使用這個的指令來註冊 《 /register <電郵> <重覆電郵> 》'
usage_unreg: '&8[&6用戶系統&8] &c用法 《 /unregister <密碼> 》'
pwd_changed: '&8[&6用戶系統&8] &c你成功的更換了你的密碼 '
user_unknown: '&8[&6用戶系統&8] &c此用戶名沒有已登記資料。'
password_error: '&8[&6用戶系統&8] &f密碼不符合。'
invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞請等待登入階段結束。'
reg_only: '&8[&6用戶系統&8] &f限已註冊會員請先到 https://www.example.com/ 註冊。'
logged_in: '&8[&6用戶系統&8] &c你已經登入過了。'
logout: '&8[&6用戶系統&8] &b你成功的登出了。'
same_nick: '&8[&6用戶系統&8] &f同名玩家已在遊玩。'
registered: '&8[&6用戶系統&8] &b你成功的註冊了。'
pass_len: '&8[&6用戶系統&8] &f你的密碼並不符合規定長度。'
reload: '&8[&6用戶系統&8] &b登入系統設定及資料庫重新載入完畢。'
timeout: '&8[&6用戶系統&8] &f登入逾時。'
usage_changepassword: '&8[&6用戶系統&8] &f用法 《 /changepassword <舊密碼> <新密碼> 》'
name_len: '&8[&6用戶系統&8] &c你的用戶名不符合規定長度。'
regex: '&8[&6用戶系統&8] &c你的用戶名含有不容許之字符。以下為准許之字母 REG_EX'
add_email: '&8[&6用戶系統&8] &b請為你的帳戶立即添加電郵地址 《 /email add <電郵地址> <重覆電郵地址> 》'
bad_database_email: '&8[&6用戶系統&8] 此指令只適用於使用MySQL或SQLite之伺服器。'
recovery_email: '&8[&6用戶系統&8] &c忘記密碼 請使用這個的指令來更新密碼: 《 /email recovery <電郵地址> 》'
usage_captcha: '&8[&6用戶系統&8] &c用法 《 /captcha <theCaptcha> 》'
# TODO wrong_captcha: Missing tag THE_CAPTCHA
wrong_captcha: '&8[&6用戶系統&8] &c你輸入了錯誤的驗證碼請使用 《 /captcha <驗證碼> 》 再次輸入。'
valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼是無效的 '
kick_forvip: '&c因為有VIP玩家登入了伺服器。'
kick_fullserver: '&c抱歉 因為伺服器滿人了,所以你目前未能登入伺服器。'
usage_email_add: '&8[&6用戶系統&8] &f用法 《 /email add <電郵> <重覆電郵> 》'
usage_email_change: '&8[&6用戶系統&8] &f用法 《 /email change <舊電郵> <新電郵> 》'
usage_email_recovery: '&8[&6用戶系統&8] &f用法 《 /email recovery <電郵> 》'
new_email_invalid: '&8[&6用戶系統&8] 你所填寫的新電郵地址並不正確。'
old_email_invalid: '&8[&6用戶系統&8] 你所填寫的舊電郵地址並不正確。'
email_invalid: '&8[&6用戶系統&8] 你所填寫的電郵地址並不正確。'
email_added: '&8[&6用戶系統&8] 已加入你的電郵地址記錄。'
email_confirm: '&8[&6用戶系統&8] 請重覆輸入你的電郵地址。'
email_changed: '&8[&6用戶系統&8] 你的電郵地址記錄已更改。'
email_send: '&8[&6用戶系統&8] 忘記密碼信件已寄出,請查收。'
country_banned: '&8[&6用戶系統&8] 本伺服器已停止對你的國家提供遊戲服務。'
antibot_auto_enabled: '&8[&6用戶系統&8] 防止機械人程序已因應現時大量不尋常的連線而啟用。'
antibot_auto_disabled: '&8[&6用戶系統&8] 防止機械人程序檢查到不正常連接數已減少,並於 %m 分鐘後停止運作。'
# TODO email_already_used: '&4The email address is already being used'
# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.'
# TODO email_exists: '&cA recovery email was already sent! You can discard it and send a new one using the command below:'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
kick_antibot: '&8[&6玩家系统&8] &f防机器人程序已启用 !请稍等几分钟後才再次进入服务器'
unknown_user: '&8[&6玩家系统&8] &f&f数据库里找不到此用户'
unsafe_spawn: '&8[&6玩家系统&8] &f你退出服务器时的位置不安全正在传送你到此世界的出生点'
not_logged_in: '&8[&6玩家系统&8] &c你还未登录'
reg_voluntarily: '&8[&6玩家系统&8] &f你可以在服务器里使用这个指令以注册“/register <密码> <再输入一次以确定密码>”'
usage_log: '&8[&6玩家系统&8] &c正确用法“/login <密码>”'
wrong_pwd: '&8[&6玩家系统&8] &c错误的密码'
unregistered: '&8[&6玩家系统&8] &c成功删除此用户'
reg_disabled: '&8[&6玩家系统&8] &c目前服务器暂时禁止注册请到服务器论坛以得到更多资讯'
valid_session: '&8[&6玩家系统&8] &c欢迎回来已帮你自动登录到此服务器'
login: '&8[&6玩家系统&8] &c已成功登录'
vb_nonActiv: '&8[&6玩家系统&8] &f你的帐号还未激活请查看你的邮箱'
user_regged: '&8[&6玩家系统&8] &c此用户已经在此服务器注册过'
usage_reg: '&8[&6玩家系统&8] &c正确用法“/register <密码> <再输入一次以确定密码>”'
max_reg: '&8[&6玩家系统&8] &f你不允许再为你的IP在服务器注册更多用户了'
no_perm: '&8[&6玩家系统&8] &c没有权限'
error: '&8[&6玩家系统&8] &f发现错误请联系管理员'
login_msg: '&8[&6玩家系统&8] &c请输入“/login <密码>”以登录'
reg_msg: '&8[&6玩家系统&8] &c请输入“/register <密码> <再输入一次以确定密码>”以注册'
reg_email_msg: '&8[&6玩家系统&8] &c请输入 "/register <邮箱> <确认电子邮件>"'
usage_unreg: '&8[&6玩家系统&8] &c正确用法“/unregister <密码>”'
pwd_changed: '&8[&6玩家系统&8] &c密码已成功修改'
user_unknown: '&8[&6玩家系统&8] &c此用户名还未注册过'
password_error: '&8[&6玩家系统&8] &f密码不相同'
password_error_nick: '&8[&6玩家系统&8] &f你不能使用你的名字作为密码。 '
password_error_unsafe: '&8[&6玩家系统&8] &f你不能使用安全性过低的码。 '
invalid_session: '&8[&6玩家系统&8] &f登陆数据异常请等待登陆结束'
reg_only: '&8[&6玩家系统&8] &f只允许注册过的玩家进服请到 https://example.cn 注册'
logged_in: '&8[&6玩家系统&8] &c你已经登陆过了'
logout: '&8[&6玩家系统&8] &c已成功登出'
same_nick: '&8[&6玩家系统&8] &f同样的用户名现在在线且已经登录了'
registered: '&8[&6玩家系统&8] &c已成功注册'
pass_len: '&8[&6玩家系统&8] &你的密码没有达到要求!'
reload: '&8[&6玩家系统&8] &f配置以及数据已经重新加载完毕'
timeout: '&8[&6玩家系统&8] &f给你登录的时间已经过了'
usage_changepassword: '&8[&6玩家系统&8] &f正确用法“/changepassword 旧密码 新密码”'
name_len: '&8[&6玩家系统&8] &c你的用户名太短或者太长了'
regex: '&8[&6玩家系统&8] &c你的用户名包含非法字母用户名里允许的字母: REG_EX'
add_email: '&8[&6玩家系统&8] &c请输入“/email add <你的邮箱> <再输入一次以确认>”以把你的邮箱添加到此帐号'
recovery_email: '&8[&6玩家系统&8] &c忘了你的密码请输入“/email recovery <你的邮箱>”'
usage_captcha: '&8[&6玩家系统&8] &c正确用法/captcha <theCaptcha>'
wrong_captcha: '&8[&6玩家系统&8] &c错误的验证码请输入“/captcha THE_CAPTCHA”'
valid_captcha: '&8[&6玩家系统&8] &c你的验证码是有效的'
kick_forvip: '&8[&6玩家系统&8] &cA VIP玩家加入了已满的服务器!'
kick_fullserver: '&8[&6玩家系统&8] &c抱歉服务器已满!'
usage_email_add: '&8[&6玩家系统&8] &f用法: /email add <邮箱> <确认电子邮件> '
usage_email_change: '&8[&6玩家系统&8] &f用法: /email change <旧邮箱> <新邮箱> '
usage_email_recovery: '&8[&6玩家系统&8] &f用法: /email recovery <邮箱>'
new_email_invalid: '&8[&6玩家系统&8] &f新邮箱无效!'
old_email_invalid: '&8[&6玩家系统&8] &f旧邮箱无效!'
email_invalid: '&8[&6玩家系统&8] &f无效的邮箱'
email_added: '&8[&6玩家系统&8] &f邮箱已添加 !'
email_confirm: '&8[&6玩家系统&8] &f确认你的邮箱 !'
email_changed: '&8[&6玩家系统&8] &f邮箱已改变 !'
email_send: '&8[&6玩家系统&8] &f恢复邮件已发送 !'
country_banned: '这个服务器禁止该国家登陆'
antibot_auto_enabled: '&8[&6玩家系统&8] &f防机器人程序由于大量异常连接而启用'
antibot_auto_disabled: '&8[&6玩家系统&8] &f防机器人程序由于异常连接减少而在 %m 分钟后停止'
email_already_used: '&8[&6玩家系统&8] &4邮箱已被使用'
email_exists: '&8[&6玩家系统&8] &c恢复邮件已发送 ! 你可以丢弃它然後使用以下的指令来发送新的邮件:'
two_factor_create: '&8[&6玩家系统&8] &2你的代码是 %code你可以使用 %url 来扫描'
not_owner_error: '&8[&6玩家系统&8] &4警告 &c你并不是此帐户持有人请立即登出。 '
invalid_name_case: '&8[&6玩家系统&8] &c你应该使用「%valid」而并非「%invalid」登入游戏。 '

View File

@ -1,67 +1,66 @@
#----------------------------------------#
#translated by i998979
#----------------------------------------#
unknown_user: '&f用戶資料並不存在於資料庫中。'
unsafe_spawn: '&f你的登出的位置不安全將傳送你至重生點。'
not_logged_in: '&c你並未登入'
reg_voluntarily: '&f請使用: /register <密碼> <重覆密碼> 來註冊。'
usage_log: '&c用法: /login <密碼>'
wrong_pwd: '&c密碼錯誤。'
unregistered: '&c成功取消該名用戶的註冊記錄。'
reg_disabled: '&c新玩家註冊已停用。'
valid_session: '&cIP記憶自動登入。'
login: '&c登入成功。'
vb_nonActiv: '&f你的帳戶並未啟用請檢查你的電郵'
user_regged: '&c此用戶名已有註冊記錄。'
usage_reg: '&c用法: /register <密碼> <重覆密碼>'
max_reg: '&f你的IP地址已達到註冊帳號上限。'
no_perm: '&c你沒有足夠的權限。'
error: '&f發生錯誤請與管理員聯絡。'
login_msg: '&c請使用 /login <密碼> 來登入。'
reg_msg: '&c請使用 /register <密碼> <重覆密碼> 來註冊。'
reg_email_msg: '&c請使用 /register <電郵> <重覆電郵> 來註冊。'
usage_unreg: '&c用法: /unregister <密碼>'
pwd_changed: '&c密碼更改成功'
user_unknown: '&c該用戶並未註冊。'
password_error: '&f密碼不符合。'
password_error_nick: '&f你不能使用你的名字作為密碼。'
password_error_unsafe: '&f你不能使用安全性過低的碼。'
invalid_session: '&f登入階段資料不相同請等待登入階段結束。'
reg_only: '&f只限已註冊用戶請先到 https://www.example.com 註冊。'
logged_in: '&c你已經登入過了。'
logout: '&b登出成功。'
same_nick: '&f同名玩家已在遊玩。'
registered: '&b註冊成功。'
pass_len: '&f你的密碼太短或太長。'
reload: '&b系統設定及資料庫已重新載入。'
timeout: '&f登入逾時請重新登入。'
usage_changepassword: '&f用法: /changepassword <舊密碼> <新密碼>'
name_len: '&c你的用戶名太短或太長。'
regex: '&c你的用戶名含有不容許的字符。以下為准許之字母: REG_EX。'
add_email: '&b請為你的帳戶添加電郵地址: /email add <電郵地址> <重覆電郵地址>。'
bad_database_email: '/email 只適用於使用MySQL或SQLite之伺服器請聯絡管理員。'
recovery_email: '&c忘記密碼請使用 /email recovery <電郵地址> 來更新密碼。'
usage_captcha: '&c用法: /captcha <theCaptcha>'
wrong_captcha: '&c驗證碼錯誤請再次輸入 /captcha THE_CAPTCHA。'
valid_captcha: '&c驗證碼無效'
kick_forvip: '&cVIP玩家登入了滿人的伺服器。'
kick_fullserver: '&c因為伺服器滿人請稍候再試。'
usage_email_add: '&f用法: /email add <電郵> <重覆電郵>'
usage_email_change: '&f用法: /email change <舊電郵> <新電郵>'
usage_email_recovery: '&f用法: /email recovery <電郵>'
new_email_invalid: '新電郵地址不正確。'
old_email_invalid: '舊電郵地址不正確。'
email_invalid: '電郵地址不正確。'
email_added: '電郵地址已加入。'
email_confirm: '請確認電郵地址。'
email_changed: '電郵地址已更改。'
email_send: '已寄出忘記密碼信件。'
country_banned: '你的國家已被本伺服器封禁。'
antibot_auto_enabled: '防止機械人程序因大量不尋常連線而啟用。'
antibot_auto_disabled: '防止機械人程序將於 %m 分鐘後停止運作。'
email_already_used: '&4邮箱已被使用'
kick_antibot: '[AuthMe] 防机器人程序已启用 !请稍等几分钟後才再次进入服务器'
email_exists: '&c恢复邮件已发送 ! 你可以丢弃它然後使用以下的指令来发送新的邮件:'
two_factor_create: '&2你的代码是 %code你可以使用 %url 来扫描'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
# Translator: lifehome<m@lifeho.me> #
# Last modif: 1459528742 UTC #
# -------------------------------------------- #
kick_antibot: '&8[&6用戶系統&8] &c伺服器錯誤請稍候再嘗試登入吧。 &7(err: kick_due2_bot)'
unknown_user: '&8[&6用戶系統&8] &f用戶資料並不存在。'
unsafe_spawn: '&8[&6用戶系統&8] &f你的登出位置不安全現在將傳送你到重生點。'
not_logged_in: '&8[&6用戶系統&8] &c你還沒有登入 '
reg_voluntarily: '&8[&6用戶系統&8] &f你可以使用這個指令來註冊 《 /register <密碼> <重覆密碼> 》'
usage_log: '&8[&6用戶系統&8] &f用法 《 /login <密碼> 》'
wrong_pwd: '&8[&6用戶系統&8] &c你輸入了錯誤的密碼。'
unregistered: '&8[&6用戶系統&8] &c你已成功刪除會員註冊記錄。'
reg_disabled: '&8[&6用戶系統&8] &c本伺服器已停止新玩家註冊。'
valid_session: '&8[&6用戶系統&8] &b嗨 歡迎回來喔~'
login: '&8[&6用戶系統&8] &c你成功登入了。'
vb_nonActiv: '&8[&6用戶系統&8] &f你的帳戶還沒有經過電郵驗證 '
user_regged: '&8[&6用戶系統&8] &c此用戶名已經註冊過了。'
usage_reg: '&8[&6用戶系統&8] &f用法 《 /register <密碼> <重覆密碼> 》'
max_reg: '&8[&6用戶系統&8] &f你的IP地址已達到註冊數上限。'
no_perm: '&8[&6用戶系統&8] &b嗯你想幹甚麼'
error: '&8[&6用戶系統&8] &f發生錯誤請與管理員聯絡。'
login_msg: '&8[&6用戶系統&8] &c請使用這個指令來登入 《 /login <密碼> 》'
reg_msg: '&8[&6用戶系統&8] &c請使用這個指令來註冊 《 /register <密碼> <重覆密碼> 》'
reg_email_msg: '&8[&6用戶系統&8] &c請使用這個指令來註冊 《 /register <電郵> <重覆電郵> 》'
usage_unreg: '&8[&6用戶系統&8] &f用法 《 /unregister <密碼> 》'
pwd_changed: '&8[&6用戶系統&8] &c你成功更換了你的密碼 '
user_unknown: '&8[&6用戶系統&8] &c此用戶名沒有已登記資料。'
password_error: '&8[&6用戶系統&8] &f密碼不符合。'
password_error_nick: '&8[&6用戶系統&8] &c這個密碼太不安全了'
password_error_unsafe: '&8[&6用戶系統&8] &c這個密碼太不安全了'
invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞請等待登入階段結束。'
reg_only: '&8[&6用戶系統&8] &f限已註冊會員請先到本服網站進行註冊。'
logged_in: '&8[&6用戶系統&8] &c你已經登入過了。'
logout: '&8[&6用戶系統&8] &b你成功登出了。'
same_nick: '&8[&6用戶系統&8] &f同名玩家已在遊玩。'
registered: '&8[&6用戶系統&8] &b你成功註冊了。'
pass_len: '&8[&6用戶系統&8] &f你的密碼並不符合規定長度。'
reload: '&8[&6用戶系統&8] &b登入系統設定及資料庫重新載入完畢。'
timeout: '&8[&6用戶系統&8] &f登入逾時。'
usage_changepassword: '&8[&6用戶系統&8] &f用法 《 /changepassword <舊密碼> <新密碼> 》'
name_len: '&8[&6用戶系統&8] &c你的用戶名不符合規定長度。'
regex: '&8[&6用戶系統&8] &c用戶名稱錯誤 登入系統只接受以下字符: REG_EX'
add_email: '&8[&6用戶系統&8] &b請為你的帳戶立即添加電郵地址 《 /email add <電郵地址> <重覆電郵地址> 》'
recovery_email: '&8[&6用戶系統&8] &b忘記密碼請使用 /email recovery <電郵地址> 來更新密碼。'
usage_captcha: '&8[&6用戶系統&8] &f用法 《 /captcha <theCaptcha> 》'
wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效請使用 《 /captcha THE_CAPTCHA 》 再次輸入。'
valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效 '
kick_forvip: '&c喔因為有VIP玩家登入了伺服器。'
kick_fullserver: '&c抱歉 因為伺服器滿人了,所以你目前未能登入伺服器。'
usage_email_add: '&8[&6用戶系統&8] &f用法 《 /email add <電郵> <重覆電郵> 》'
usage_email_change: '&8[&6用戶系統&8] &f用法 《 /email change <舊電郵> <新電郵> 》'
usage_email_recovery: '&8[&6用戶系統&8] &f用法 《 /email recovery <電郵> 》'
new_email_invalid: '&8[&6用戶系統&8] &c你所填寫的新電郵地址並不正確。'
old_email_invalid: '&8[&6用戶系統&8] &c你所填寫的舊電郵地址並不正確。'
email_invalid: '&8[&6用戶系統&8] &c你所填寫的電郵地址並不正確。'
email_added: '&8[&6用戶系統&8] &a已新增你的電郵地址。'
email_confirm: '&8[&6用戶系統&8] &5請重覆輸入你的電郵地址。'
email_changed: '&8[&6用戶系統&8] &a你的電郵地址已更改。'
email_send: '&8[&6用戶系統&8] &a忘記密碼信件已寄出請查收。'
country_banned: '&8[&6用戶系統&8] &4本伺服器已停止對你的國家提供遊戲服務。'
antibot_auto_enabled: '&8[&6用戶系統&8] &3防止機械人程序已因應現時大量不尋常連線而啟用。'
antibot_auto_disabled: '&8[&6用戶系統&8] &3不正常連接數已減少防止機械人程序將於 %m 分鐘後停止。'
email_already_used: '&8[&6用戶系統&8] &4這個電郵地址已被使用。'
email_exists: '&8[&6用戶系統&8] &c訊息已發送如果你收不到該封電郵可以使用以下指令進行重寄'
two_factor_create: '&8[&6用戶系統 - 兩步驗證碼&8] &b你的登入金鑰為&9「%c%code&9」&b掃描連結為&c %url'
not_owner_error: '&8[&6用戶系統&8] &4警告&c你並不是此帳戶持有人請立即登出。'
invalid_name_case: '&8[&6用戶系統&8] &4警告&c你應該使用「%valid」而並非「%invalid」登入遊戲。'

View File

@ -1,6 +1,7 @@
# Translator: MineWolf50
# Last Time Edit : 2015 / 7 / 14 , A.M.10:14
# = = = = = = = = = = = = = = = = = = = = = = = #
# Translator: MineWolf50, lifehome #
# Last modif: 1459528742 UTC #
# -------------------------------------------- #
kick_antibot: '&b【AuthMe】&cAntiBotMod 正在啟用中,請稍後再嘗試登入吧!'
unknown_user: "&b【AuthMe】&6沒有在資料庫內找到該玩家。"
unsafe_spawn: '&b【AuthMe】&6你登出的地點不安全已傳送你到安全的地點。'
not_logged_in: '&b【AuthMe】&6你還沒有登入!'
@ -9,8 +10,6 @@ usage_log: '&b【AuthMe】&6用法: &c"/login <密碼>"'
wrong_pwd: '&b【AuthMe】&6密碼錯誤!'
unregistered: '&b【AuthMe】&6你已經成功取消註冊。'
reg_disabled: '&b【AuthMe】&6已關閉註冊功能'
password_error_nick: '&b【AuthMe】&6你不可以用你的 ID ( 名稱 ) 來當作密碼 !'
password_error_unsafe: '&b【AuthMe】&6你不可以使用這個不安全的密碼'
valid_session: '&b【AuthMe】&6你已經成功登入!'
login: '&b【AuthMe】&6密碼正確你已成功登入!'
vb_nonActiv: '&b【AuthMe】&6你的帳號還沒有經過驗證! 檢查看看你的電子信箱 (Email) 吧!'
@ -26,8 +25,10 @@ usage_unreg: '&b【AuthMe】&6用法: &c"/unregister <密碼>"'
pwd_changed: '&b【AuthMe】&6密碼變更成功!'
user_unknown: '&b【AuthMe】&6這個帳號還沒有註冊過'
password_error: '&b【AuthMe】&6兩次輸入的密碼不一致!'
password_error_nick: '&b【AuthMe】&6你不可以用你的 ID ( 名稱 ) 來當作密碼 !'
password_error_unsafe: '&b【AuthMe】&6你不可以使用這個不安全的密碼'
invalid_session: '&b【AuthMe】&6憑證日期不相符!'
reg_only: '&b【AuthMe】&6請到下列網站 :「 http://example.com 」 進行註冊'
reg_only: '&b【AuthMe】&6請到下列網站 :「 https://example.tw 」 進行註冊'
logged_in: '&b【AuthMe】&6你已經登入了!'
logout: '&b【AuthMe】&6你已成功登出'
same_nick: '&b【AuthMe】&6有同樣帳號的玩家在線上!'
@ -37,13 +38,11 @@ reload: '&b【AuthMe】&6已重新讀取設定檔及資料庫'
timeout: '&b【AuthMe】&6超過登入時間請稍後再試一次'
usage_changepassword: '&b【AuthMe】&6用法: &c"/changepassword <舊密碼> <新密碼>"'
name_len: '&b【AuthMe】&6你的暱稱 太長 / 太短 了!'
# TODO regex: Missing tag REG_EX
regex: '&b【AuthMe】&6暱稱裡包含不能使用的字符'
regex: '&b【AuthMe】&6暱稱裡能使用的字符為 REG_EX'
add_email: '&b【AuthMe】&6請使用 &c"/email add <你的Email> <再次輸入你的Email>" &6來添加 Email'
recovery_email: '&b【AuthMe】&6忘記密碼了嗎? 使用 &c"/email recovery <你的Email>"'
usage_captcha: '&b【AuthMe】&6請用 &c"/captcha <theCaptcha>" &6來輸入你的驗證碼'
# TODO wrong_captcha: Missing tag THE_CAPTCHA
wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼'
wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼請使用 《 /captcha THE_CAPTCHA 》 再試一次吧。'
valid_captcha: '&b【AuthMe】&6驗證碼無效!'
kick_forvip: '&b【AuthMe】&6你已經被請出。&c原因 : 有 VIP 玩家登入伺服器'
kick_fullserver: '&b【AuthMe】&6伺服器已經滿了請等等再試一次'
@ -57,12 +56,11 @@ email_added: '&b【AuthMe】&6已添加Email!'
email_confirm: '&b【AuthMe】&6請驗證你的Email!'
email_changed: '&b【AuthMe】&6Email已變更!'
email_send: '&b【AuthMe】&6已經送出重設密碼要求至你的Email , 請查收。'
email_exists: '&b【AuthMe】&6這個帳戶已經有設定電子郵件了'
country_banned: '&b【AuthMe】&6你所在的地區無法進入此伺服器'
antibot_auto_enabled: '&b【AuthMe】&6AntiBotMod已自動啟用!'
antibot_auto_disabled: '&b【AuthMe】&6AntiBotMod將會於 &c%m &6分鐘後自動關閉'
# TODO email_already_used: '&4The email address is already being used'
# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
email_already_used: '&b【AuthMe】&4這個電郵地址已被使用。'
email_exists: '&b【AuthMe】&6這個帳戶已經有設定電子郵件了'
two_factor_create: '&b【AuthMe - 兩步驗證碼】&b你的登入金鑰為&9「%c%code&9」&b掃描連結為&c %url'
not_owner_error: '&b【AuthMe】&4警告&c你並不是此帳戶持有人請立即登出。'
invalid_name_case: '&b【AuthMe】&4警告&c你應該使用「%valid」而並非「%invalid」登入遊戲。'

View File

@ -167,6 +167,7 @@ public class AntiBotTest {
antiBot.checkAntiBot(player);
// then
@SuppressWarnings("unchecked")
List<String> playerList = (List<String>) ReflectionTestUtils
.getFieldValue(AntiBot.class, antiBot, "antibotPlayers");
assertThat(playerList, hasSize(1));
@ -196,6 +197,7 @@ public class AntiBotTest {
antiBot.checkAntiBot(player);
// then
@SuppressWarnings("rawtypes")
List<?> playerList = (List) ReflectionTestUtils.getFieldValue(AntiBot.class, antiBot, "antibotPlayers");
assertThat(playerList, empty());
verify(bukkitService, never()).scheduleSyncDelayedTask(any(Runnable.class), anyLong());

View File

@ -1,20 +0,0 @@
package fr.xephi.authme;
import org.mockito.Mockito;
import java.util.logging.Logger;
/**
* Test initializer for {@link ConsoleLogger}.
*/
public class ConsoleLoggerTestInitializer {
private ConsoleLoggerTestInitializer() {
}
public static Logger setupLogger() {
Logger logger = Mockito.mock(Logger.class);
ConsoleLogger.setLogger(logger);
return logger;
}
}

View File

@ -3,11 +3,16 @@ package fr.xephi.authme;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.util.BukkitService;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Logger;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.verify;
@ -68,20 +73,6 @@ public final class TestHelper {
runnable.run();
}
/**
* Execute a {@link Runnable} passed to a mock's {@link BukkitService#scheduleSyncDelayedTask(Runnable)} method.
* Note that calling this method expects that there be a runnable sent to the method and will fail
* otherwise.
*
* @param service The mock service
*/
public static void runSyncDelayedTask(BukkitService service) {
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
verify(service).scheduleSyncDelayedTask(captor.capture());
Runnable runnable = captor.getValue();
runnable.run();
}
/**
* Execute a {@link Runnable} passed to a mock's {@link BukkitService#scheduleSyncDelayedTask(Runnable, long)}
* method. Note that calling this method expects that there be a runnable sent to the method and will fail
@ -96,4 +87,42 @@ public final class TestHelper {
runnable.run();
}
/**
* Assign the necessary fields on ConsoleLogger with mocks.
*
* @return The logger mock used
*/
public static Logger setupLogger() {
Logger logger = Mockito.mock(Logger.class);
ConsoleLogger.setLogger(logger);
return logger;
}
/**
* Check that a class only has a hidden, zero-argument constructor, preventing the
* instantiation of such classes (utility classes). Invokes the hidden constructor
* as to register the code coverage.
*
* @param clazz The class to validate
*/
public static void validateHasOnlyPrivateEmptyConstructor(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
if (constructors.length > 1) {
throw new IllegalStateException("Class " + clazz.getSimpleName() + " has more than one constructor");
} else if (constructors[0].getParameterTypes().length != 0) {
throw new IllegalStateException("Constructor of " + clazz + " does not have empty parameter list");
} else if (!Modifier.isPrivate(constructors[0].getModifiers())) {
throw new IllegalStateException("Constructor of " + clazz + " is not private");
}
// Ugly hack to get coverage on the private constructors
// http://stackoverflow.com/questions/14077842/how-to-test-a-private-constructor-in-java-application
try {
constructors[0].setAccessible(true);
constructors[0].newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new UnsupportedOperationException(e);
}
}
}

View File

@ -1,64 +0,0 @@
package fr.xephi.authme.cache;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import org.bukkit.entity.Player;
import org.junit.Test;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Test for {@link IpAddressManager}.
*/
public class IpAddressManagerTest {
@Test
public void shouldRetrieveFromCache() {
// given
IpAddressManager ipAddressManager = new IpAddressManager(mockSettings(true));
ipAddressManager.addCache("Test", "my test IP");
// when
String result = ipAddressManager.getPlayerIp(mockPlayer("test", "123.123.123.123"));
// then
assertThat(result, equalTo("my test IP"));
}
@Test
public void shouldReturnPlainIp() {
// given
IpAddressManager ipAddressManager = new IpAddressManager(mockSettings(false));
// when
String result = ipAddressManager.getPlayerIp(mockPlayer("bobby", "8.8.8.8"));
// then
assertThat(result, equalTo("8.8.8.8"));
}
private static NewSetting mockSettings(boolean useVeryGames) {
NewSetting settings = mock(NewSetting.class);
given(settings.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)).willReturn(useVeryGames);
return settings;
}
private static Player mockPlayer(String name, String ip) {
Player player = mock(Player.class);
given(player.getName()).willReturn(name);
InetAddress inetAddress = mock(InetAddress.class);
given(inetAddress.getHostAddress()).willReturn(ip);
InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 8093);
given(player.getAddress()).willReturn(inetSocketAddress);
return player;
}
}

View File

@ -17,13 +17,14 @@ import static fr.xephi.authme.command.FoundResultStatus.NO_PERMISSION;
import static fr.xephi.authme.command.FoundResultStatus.SUCCESS;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
@ -95,11 +96,8 @@ public class CommandHandlerTest {
// then
verify(serviceMock).mapPartsToCommand(eq(sender), captor.capture());
assertThat(captor.getValue(), contains("unreg", "testPlayer"));
verify(command, never()).getExecutableCommand();
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString("don't have permission"));
verify(sender).sendMessage(argThat(containsString("don't have permission")));
}
@Test
@ -170,11 +168,8 @@ public class CommandHandlerTest {
// then
verify(serviceMock).mapPartsToCommand(eq(sender), captor.capture());
assertThat(captor.getValue(), contains("unreg", "testPlayer"));
verify(command, never()).getExecutableCommand();
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString("Failed to parse"));
verify(sender).sendMessage(argThat(containsString("Failed to parse")));
}
@Test

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.command;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
import org.junit.Test;
@ -38,7 +37,6 @@ public class CommandInitializerTest {
@BeforeClass
public static void initializeCommandManager() {
WrapperMock.createInstance();
commands = CommandInitializer.buildCommands();
}

View File

@ -13,12 +13,12 @@ import java.util.Set;
import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
@ -31,7 +31,7 @@ public class CommandMapperTest {
private static Set<CommandDescription> commands;
private static CommandMapper mapper;
private static PermissionsManager permissionsManagerMock;
private static PermissionsManager permissionsManager;
@BeforeClass
public static void setUpCommandHandler() {
@ -40,8 +40,8 @@ public class CommandMapperTest {
@Before
public void setUpMocks() {
permissionsManagerMock = mock(PermissionsManager.class);
mapper = new CommandMapper(commands, permissionsManagerMock);
permissionsManager = mock(PermissionsManager.class);
mapper = new CommandMapper(commands, permissionsManager);
}
// -----------
@ -52,7 +52,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "login", "test1");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -71,7 +71,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("Authme", "REG", "arg1", "arg2");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -89,7 +89,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "register", "pass123", "pass123", "pass123");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -107,7 +107,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "Reg");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -125,7 +125,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "reh", "pass123", "pass123");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -144,7 +144,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "asdfawetawty4asdca");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -162,7 +162,7 @@ public class CommandMapperTest {
// given
List<String> parts = singletonList("unregister");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -180,7 +180,7 @@ public class CommandMapperTest {
// given
List<String> parts = asList("bogus", "label1", "arg1");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -205,7 +205,7 @@ public class CommandMapperTest {
// given
List<String> parts = asList("Unreg", "player1");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -223,7 +223,7 @@ public class CommandMapperTest {
// given
List<String> parts = asList("unregistER", "player1", "wrongArg");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -241,7 +241,7 @@ public class CommandMapperTest {
// given
List<String> parts = asList("email", "helptest", "arg1");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(true);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);
@ -259,7 +259,7 @@ public class CommandMapperTest {
// given
List<String> parts = Arrays.asList("authme", "login", "test1");
CommandSender sender = mock(CommandSender.class);
given(permissionsManagerMock.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(false);
given(permissionsManager.hasPermission(eq(sender), any(CommandDescription.class))).willReturn(false);
// when
FoundCommandResult result = mapper.mapPartsToCommand(sender, parts);

View File

@ -2,7 +2,6 @@ package fr.xephi.authme.command;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
@ -15,6 +14,8 @@ import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.ValidationService;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
@ -27,8 +28,8 @@ import org.mockito.runners.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@ -56,18 +57,20 @@ public class CommandServiceTest {
@Mock
private NewSetting settings;
@Mock
private IpAddressManager ipAddressManager;
@Mock
private PluginHooks pluginHooks;
@Mock
private SpawnLoader spawnLoader;
@Mock
private AntiBot antiBot;
@Mock
private ValidationService validationService;
@Mock
private BukkitService bukkitService;
@Before
public void setUpService() {
commandService = new CommandService(authMe, commandMapper, helpProvider, messages, passwordSecurity,
permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader, antiBot);
permissionsManager, settings, pluginHooks, spawnLoader, antiBot, validationService, bukkitService);
}
@Test
@ -221,11 +224,63 @@ public class CommandServiceTest {
}
@Test
public void shouldReturnIpAddressManager() {
// given/when
IpAddressManager ipManager = commandService.getIpAddressManager();
public void shouldValidatePassword() {
// given
String user = "asdf";
String password = "mySecret55";
given(validationService.validatePassword(password, user)).willReturn(MessageKey.INVALID_PASSWORD_LENGTH);
// when
MessageKey result = commandService.validatePassword(password, user);
// then
assertThat(ipManager, equalTo(ipAddressManager));
assertThat(result, equalTo(MessageKey.INVALID_PASSWORD_LENGTH));
verify(validationService).validatePassword(password, user);
}
@Test
public void shouldValidateEmail() {
// given
String email = "test@example.tld";
given(validationService.validateEmail(email)).willReturn(true);
// when
boolean result = commandService.validateEmail(email);
// then
assertThat(result, equalTo(true));
verify(validationService).validateEmail(email);
}
@Test
public void shouldCheckIfEmailCanBeUsed() {
// given
String email = "mail@example.com";
CommandSender sender = mock(CommandSender.class);
given(validationService.isEmailFreeForRegistration(email, sender))
.willReturn(true);
// when
boolean result = commandService.isEmailFreeForRegistration(email, sender);
// then
assertThat(result, equalTo(true));
verify(validationService).isEmailFreeForRegistration(email, sender);
}
@Test
public void shouldGetPlayer() {
// given
String playerName = "_tester";
Player player = mock(Player.class);
given(bukkitService.getPlayerExact(playerName)).willReturn(player);
// when
Player result = commandService.getPlayer(playerName);
// then
assertThat(result, equalTo(player));
verify(bukkitService).getPlayerExact(playerName);
}
}

View File

@ -4,14 +4,13 @@ import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -28,12 +27,10 @@ public class PlayerCommandTest {
PlayerCommandImpl command = new PlayerCommandImpl();
// when
command.executeCommand(sender, Collections.<String> emptyList(), mock(CommandService.class));
command.executeCommand(sender, Collections.<String>emptyList(), mock(CommandService.class));
// then
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender, times(1)).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString("only for players"));
verify(sender).sendMessage(argThat(containsString("only for players")));
}
@Test
@ -58,12 +55,10 @@ public class PlayerCommandTest {
PlayerCommandWithAlt command = new PlayerCommandWithAlt();
// when
command.executeCommand(sender, Collections.<String> emptyList(), mock(CommandService.class));
command.executeCommand(sender, Collections.<String>emptyList(), mock(CommandService.class));
// then
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender, times(1)).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString("use /authme test <command> instead"));
verify(sender, times(1)).sendMessage(argThat(containsString("use /authme test <command> instead")));
}

View File

@ -14,8 +14,8 @@ import java.util.Collections;
import java.util.List;
import static fr.xephi.authme.TestHelper.runInnerRunnable;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
@ -81,7 +81,7 @@ public class AccountsCommandTest {
// given
List<String> arguments = Collections.singletonList("SomeUser");
given(dataSource.getAuth("someuser")).willReturn(mock(PlayerAuth.class));
given(dataSource.getAllAuthsByIp(anyString())).willReturn(Collections.<String> emptyList());
given(dataSource.getAllAuthsByIp(anyString())).willReturn(Collections.<String>emptyList());
// when
command.executeCommand(sender, arguments, service);
@ -115,7 +115,7 @@ public class AccountsCommandTest {
public void shouldReturnIpUnknown() {
// given
List<String> arguments = Collections.singletonList("123.45.67.89");
given(dataSource.getAllAuthsByIp("123.45.67.89")).willReturn(Collections.<String> emptyList());
given(dataSource.getAllAuthsByIp("123.45.67.89")).willReturn(Collections.<String>emptyList());
// when
command.executeCommand(sender, arguments, service);

View File

@ -8,7 +8,7 @@ import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;

View File

@ -1,7 +1,6 @@
package fr.xephi.authme.command.executable.authme;
import com.google.common.base.Strings;
import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
@ -10,12 +9,12 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.command.CommandSender;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Arrays;
@ -29,97 +28,33 @@ import static org.mockito.Mockito.verify;
/**
* Test for {@link ChangePasswordAdminCommand}.
*/
@RunWith(MockitoJUnitRunner.class)
public class ChangePasswordAdminCommandTest {
@Mock
private CommandService service;
@BeforeClass
public static void setUpLogger() {
ConsoleLoggerTestInitializer.setupLogger();
}
@Before
public void setUpServiceMock() {
service = mock(CommandService.class);
given(service.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX)).willReturn("[a-zA-Z]+");
given(service.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)).willReturn(3);
given(service.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)).willReturn(20);
given(service.getProperty(SecuritySettings.UNSAFE_PASSWORDS))
.willReturn(Arrays.asList("unsafe", "otherUnsafe"));
TestHelper.setupLogger();
}
@Test
public void shouldRejectPasswordSameAsUsername() {
public void shouldRejectInvalidPassword() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
given(service.validatePassword("Bobby", "bobby")).willReturn(MessageKey.PASSWORD_IS_USERNAME_ERROR);
// when
command.executeCommand(sender, Arrays.asList("bobby", "Bobby"), service);
// then
verify(service).validatePassword("Bobby", "bobby");
verify(service).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
verify(service, never()).getDataSource();
}
@Test
public void shouldRejectPasswordNotMatchingPattern() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
// service mock returns pattern a-zA-Z -> numbers should not be accepted
String invalidPassword = "invalid1234";
// when
command.executeCommand(sender, Arrays.asList("myPlayer123", invalidPassword), service);
// then
verify(service).send(sender, MessageKey.PASSWORD_MATCH_ERROR);
verify(service, never()).getDataSource();
}
@Test
public void shouldRejectTooShortPassword() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
// when
command.executeCommand(sender, Arrays.asList("player", "ab"), service);
// then
verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
verify(service, never()).getDataSource();
}
@Test
public void shouldRejectTooLongPassword() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
// when
command.executeCommand(sender, Arrays.asList("player", Strings.repeat("a", 30)), service);
// then
verify(service).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
verify(service, never()).getDataSource();
}
@Test
public void shouldRejectUnsafePassword() {
// given
ExecutableCommand command = new ChangePasswordAdminCommand();
CommandSender sender = mock(CommandSender.class);
// when
command.executeCommand(sender, Arrays.asList("player", "unsafe"), service);
// then
verify(service).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
verify(service, never()).getDataSource();
}
@Test
public void shouldRejectCommandForUnknownUser() {
// given
@ -173,6 +108,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);
@ -209,6 +145,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);
@ -244,6 +181,7 @@ public class ChangePasswordAdminCommandTest {
runInnerRunnable(service);
// then
verify(service).validatePassword(password, player);
verify(service).send(sender, MessageKey.ERROR);
verify(passwordSecurity).computeHash(password, player);
verify(auth).setPassword(hashedPassword);

View File

@ -6,14 +6,13 @@ import fr.xephi.authme.settings.SpawnLoader;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -36,7 +35,7 @@ public class FirstSpawnCommandTest {
ExecutableCommand command = new FirstSpawnCommand();
// when
command.executeCommand(player, Collections.<String> emptyList(), service);
command.executeCommand(player, Collections.<String>emptyList(), service);
// then
verify(player).teleport(firstSpawn);
@ -54,12 +53,10 @@ public class FirstSpawnCommandTest {
ExecutableCommand command = new FirstSpawnCommand();
// when
command.executeCommand(player, Collections.<String> emptyList(), service);
command.executeCommand(player, Collections.<String>emptyList(), service);
// then
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(player).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString("spawn has failed"));
verify(player).sendMessage(argThat(containsString("spawn has failed")));
verify(player, never()).teleport(any(Location.class));
}
}

View File

@ -0,0 +1,146 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.process.Management;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* Test for {@link ForceLoginCommand}.
*/
@RunWith(MockitoJUnitRunner.class)
public class ForceLoginCommandTest {
@Mock
private CommandService commandService;
@Test
public void shouldRejectOfflinePlayer() {
// given
String playerName = "Bobby";
Player player = mockPlayer(false, playerName);
given(commandService.getPlayer(playerName)).willReturn(player);
CommandSender sender = mock(CommandSender.class);
ExecutableCommand command = new ForceLoginCommand();
// when
command.executeCommand(sender, Collections.singletonList(playerName), commandService);
// then
verify(commandService).getPlayer(playerName);
verify(sender).sendMessage(argThat(equalTo("Player needs to be online!")));
verify(commandService, never()).getManagement();
}
@Test
public void shouldRejectInexistentPlayer() {
// given
String playerName = "us3rname01";
given(commandService.getPlayer(playerName)).willReturn(null);
CommandSender sender = mock(CommandSender.class);
ExecutableCommand command = new ForceLoginCommand();
// when
command.executeCommand(sender, Collections.singletonList(playerName), commandService);
// then
verify(commandService).getPlayer(playerName);
verify(sender).sendMessage(argThat(equalTo("Player needs to be online!")));
verify(commandService, never()).getManagement();
}
@Test
public void shouldRejectPlayerWithMissingPermission() {
// given
String playerName = "testTest";
Player player = mockPlayer(true, playerName);
given(commandService.getPlayer(playerName)).willReturn(player);
PermissionsManager permissionsManager = mock(PermissionsManager.class);
given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(false);
given(commandService.getPermissionsManager()).willReturn(permissionsManager);
CommandSender sender = mock(CommandSender.class);
ExecutableCommand command = new ForceLoginCommand();
// when
command.executeCommand(sender, Collections.singletonList(playerName), commandService);
// then
verify(commandService).getPlayer(playerName);
verify(sender).sendMessage(argThat(containsString("You cannot force login the player")));
verify(commandService, never()).getManagement();
}
@Test
public void shouldForceLoginPlayer() {
// given
String playerName = "tester23";
Player player = mockPlayer(true, playerName);
given(commandService.getPlayer(playerName)).willReturn(player);
PermissionsManager permissionsManager = mock(PermissionsManager.class);
given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(true);
given(commandService.getPermissionsManager()).willReturn(permissionsManager);
Management management = mock(Management.class);
given(commandService.getManagement()).willReturn(management);
CommandSender sender = mock(CommandSender.class);
ExecutableCommand command = new ForceLoginCommand();
// when
command.executeCommand(sender, Collections.singletonList(playerName), commandService);
// then
verify(commandService).getPlayer(playerName);
verify(management).performLogin(eq(player), anyString(), eq(true));
}
@Test
public void shouldForceLoginSenderSelf() {
// given
String senderName = "tester23";
Player player = mockPlayer(true, senderName);
given(commandService.getPlayer(senderName)).willReturn(player);
PermissionsManager permissionsManager = mock(PermissionsManager.class);
given(permissionsManager.hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)).willReturn(true);
given(commandService.getPermissionsManager()).willReturn(permissionsManager);
Management management = mock(Management.class);
given(commandService.getManagement()).willReturn(management);
CommandSender sender = mock(CommandSender.class);
given(sender.getName()).willReturn(senderName);
ExecutableCommand command = new ForceLoginCommand();
// when
command.executeCommand(sender, Collections.<String>emptyList(), commandService);
// then
verify(commandService).getPlayer(senderName);
verify(management).performLogin(eq(player), anyString(), eq(true));
}
private static Player mockPlayer(boolean isOnline, String name) {
Player player = mock(Player.class);
given(player.isOnline()).willReturn(isOnline);
given(player.getName()).willReturn(name);
return player;
}
}

View File

@ -7,13 +7,12 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import org.bukkit.command.CommandSender;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.Collections;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@ -61,8 +60,6 @@ public class GetEmailCommandTest {
command.executeCommand(sender, Collections.singletonList(user), service);
// then
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender).sendMessage(captor.capture());
assertThat(captor.getValue(), containsString(email));
verify(sender).sendMessage(argThat(containsString(email)));
}
}

Some files were not shown because too many files have changed in this diff Show More