diff --git a/.checkstyle.xml b/.checkstyle.xml index e95b05192e..b92fc345cb 100644 --- a/.checkstyle.xml +++ b/.checkstyle.xml @@ -150,7 +150,6 @@ - @@ -162,7 +161,6 @@ - diff --git a/docs/commands.md b/docs/commands.md index ef8f28a8a6..542b09c099 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,5 +1,5 @@ - + ## AuthMe Commands You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >` @@ -24,9 +24,9 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
Requires `authme.admin.changemail` - **/authme getip** <player>: Get the IP address of the specified online player.
Requires `authme.admin.getip` -- **/authme totp** <player>: Returns whether the specified player has enabled two-factor authentication +- **/authme totp** <player>: Returns whether the specified player has enabled two-factor authentication.
Requires `authme.admin.totpviewstatus` -- **/authme disabletotp** <player>: Disable two-factor authentication for a player +- **/authme disabletotp** <player>: Disable two-factor authentication for a player.
Requires `authme.admin.totpdisable` - **/authme spawn**: Teleport to the spawn.
Requires `authme.admin.spawn` @@ -105,7 +105,6 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
Requires `authme.player.security.verificationcode` - **/verification help** [query]: View detailed help for /verification commands. - --- -This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Aug 02 16:25:51 CEST 2019 +This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat May 16 15:10:08 CEST 2020 diff --git a/docs/translations.md b/docs/translations.md index 33142daf13..22be81b39b 100644 --- a/docs/translations.md +++ b/docs/translations.md @@ -1,5 +1,5 @@ - + # AuthMe Translations The following translations are available in AuthMe. Set `messagesLanguage` to the language code @@ -14,10 +14,10 @@ Code | Language | Translated |   [de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 99% | 99 [eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 79% | 79 [es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 99% | 99 -[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 99% | 99 +[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | 100 [eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 42% | 42 [fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 45% | 45 -[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 99% | 99 +[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 100% | 100 [gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 48% | 48 [hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 99% | 99 [id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 93% | 93 @@ -26,13 +26,13 @@ Code | Language | Translated |   [lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 36% | 36 [nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 100% | 100 [pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 99% | 99 -[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 99% | 99 +[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 100% | 100 [ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 79% | 79 [ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 100% | 100 [si](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_si.yml) | Slovenian | 99% | 99 [sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 79% | 79 [sr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sr.yml) | Serbian | 99% | 99 -[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 99% | 99 +[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 100% | 100 [uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 100% | 100 [vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 77% | 77 [zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 100% | 100 @@ -42,4 +42,4 @@ Code | Language | Translated |   --- -This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Dec 28 12:03:51 CET 2019 +This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat May 16 15:10:13 CEST 2020 diff --git a/pom.xml b/pom.xml index 7da9bda178..314ee62e1e 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ jenkins - http://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/ + https://ci.codemc.io/job/AuthMe/job/AuthMeReloaded/ @@ -37,18 +37,18 @@ codemc-snapshots - https://repo.codemc.org/repository/maven-snapshots/ + https://repo.codemc.io/repository/maven-snapshots/ codemc-releases - https://repo.codemc.org/repository/maven-releases/ + https://repo.codemc.io/repository/maven-releases/ The GNU General Public Licence version 3 (GPLv3) - http://www.gnu.org/licenses/gpl-3.0.html + https://www.gnu.org/licenses/gpl-3.0.html repo @@ -64,7 +64,7 @@ 3.3.9 - 1.15-R0.1-SNAPSHOT + 1.15.2-R0.1-SNAPSHOT AuthMe @@ -151,7 +151,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.2.0 @@ -282,7 +282,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.2.4 package @@ -358,6 +358,7 @@ fr.xephi.authme.libs.org.bstats + @@ -388,7 +389,7 @@ org.apache.maven.plugins maven-site-plugin - 3.8.2 + 3.9.1 @@ -404,6 +405,18 @@ + + + apache-snapshots + https://repository.apache.org/content/repositories/snapshots/ + + false + + + true + + + spigotmc-repo @@ -419,7 +432,7 @@ codemc-repo - https://repo.codemc.org/repository/maven-public/ + https://repo.codemc.io/repository/maven-public/ true @@ -443,7 +456,7 @@ dmulloy2-repo-releases - http://repo.dmulloy2.net/nexus/repository/releases/ + https://repo.dmulloy2.net/nexus/repository/releases/ true @@ -453,7 +466,7 @@ dmulloy2-repo-snapshots - http://repo.dmulloy2.net/nexus/repository/snapshots/ + https://repo.dmulloy2.net/nexus/repository/snapshots/ false @@ -465,7 +478,7 @@ onarandombox-repo-releases - http://repo.onarandombox.com/content/repositories/multiverse/ + https://repo.onarandombox.com/content/repositories/multiverse/ true @@ -475,29 +488,7 @@ onarandombox-repo-snapshots - http://repo.onarandombox.com/content/repositories/multiverse-snapshots/ - - false - - - true - - - - - - vault-repo-releases - http://nexus.hc.to/content/repositories/pub_releases - - true - - - false - - - - vault-repo-snapshots - http://nexus.hc.to/content/repositories/pub_snapshots + https://repo.onarandombox.com/content/repositories/multiverse-snapshots/ false @@ -531,7 +522,7 @@ com.maxmind.db maxmind-db-gson - 2.0.2-SNAPSHOT + 2.0.3 true @@ -553,7 +544,7 @@ org.apache.commons commons-email - 1.5 + 1.6-SNAPSHOT true @@ -569,7 +560,7 @@ com.zaxxer HikariCP - 3.4.2 + 3.4.5 true @@ -598,7 +589,7 @@ de.mkammerer argon2-jvm-nolibs - 2.6 + 2.7 true @@ -606,11 +597,11 @@ com.warrenstrange googleauth - 1.4.0 + 1.5.0 true - + org.spigotmc spigot-api @@ -692,7 +683,7 @@ net.luckperms api - 5.0 + 5.1 provided @@ -728,7 +719,7 @@ - + net.milkbowl.vault VaultAPI @@ -746,7 +737,7 @@ - + com.onarandombox.multiversecore Multiverse-Core @@ -877,7 +868,7 @@ org.postgresql postgresql - 42.2.9 + 42.2.14 @@ -900,7 +891,7 @@ org.mockito mockito-core test - 3.2.4 + 3.3.3 hamcrest-core @@ -913,7 +904,7 @@ org.checkerframework checker-qual - 3.1.0 + 3.4.1 test @@ -921,7 +912,7 @@ org.xerial sqlite-jdbc - 3.30.1 + 3.32.3 test diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index d5ebc38b1b..0df8ec6186 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -20,6 +20,7 @@ import fr.xephi.authme.listener.PlayerListener19Spigot; import fr.xephi.authme.listener.ServerListener; import fr.xephi.authme.output.ConsoleLoggerFactory; +import fr.xephi.authme.process.AsyncUserScheduler; import fr.xephi.authme.security.crypts.Sha256; import fr.xephi.authme.service.BackupService; import fr.xephi.authme.service.BukkitService; @@ -67,6 +68,7 @@ public class AuthMe extends JavaPlugin { private Settings settings; private DataSource database; private BukkitService bukkitService; + private AsyncUserScheduler asyncUserScheduler; private Injector injector; private BackupService backupService; private ConsoleLogger logger; @@ -249,6 +251,7 @@ private void initialize() { void instantiateServices(Injector injector) { database = injector.getSingleton(DataSource.class); bukkitService = injector.getSingleton(BukkitService.class); + asyncUserScheduler = injector.getSingleton(AsyncUserScheduler.class); commandHandler = injector.getSingleton(CommandHandler.class); backupService = injector.getSingleton(BackupService.class); diff --git a/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java b/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java index 93204275a6..ca133c516c 100644 --- a/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java +++ b/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Optional; /** * The current API of AuthMe. @@ -133,20 +134,17 @@ public Location getLastLocation(Player player) { } /** - * Get the registration ip address of a player. + * Returns the AuthMe info of the given player's name, or empty optional if the player doesn't exist. * - * @param playerName The name of the player to process - * @return The registration ip address of the player + * @param playerName The player name to look up + * @return AuthMe player info, or empty optional if the player doesn't exist */ - public String getRegistrationIp(String playerName) { + public Optional getPlayerInfo(String playerName) { PlayerAuth auth = playerCache.getAuth(playerName); if (auth == null) { auth = dataSource.getAuth(playerName); } - if (auth != null) { - return auth.getRegistrationIp(); - } - return null; + return AuthMePlayerImpl.fromPlayerAuth(auth); } /** @@ -180,7 +178,6 @@ public List getNamesByIp(String address) { * Get the last (AuthMe) login date of a player. * * @param playerName The name of the player to process - * * @return The date of the last login, or null if the player doesn't exist or has never logged in * @deprecated Use Java 8's Instant method {@link #getLastLoginTime(String)} */ @@ -213,29 +210,6 @@ private Long getLastLoginMillis(String playerName) { return null; } - /** - * Get the registration (AuthMe) timestamp of a player. - * - * @param playerName The name of the player to process - * - * @return The timestamp of when the player was registered, or null if the player doesn't exist or is not registered - */ - public Instant getRegistrationTime(String playerName) { - Long registrationDate = getRegistrationMillis(playerName); - return registrationDate == null ? null : Instant.ofEpochMilli(registrationDate); - } - - private Long getRegistrationMillis(String playerName) { - PlayerAuth auth = playerCache.getAuth(playerName); - if (auth == null) { - auth = dataSource.getAuth(playerName); - } - if (auth != null) { - return auth.getRegistrationDate(); - } - return null; - } - /** * Return whether the player is registered. * diff --git a/src/main/java/fr/xephi/authme/api/v3/AuthMePlayer.java b/src/main/java/fr/xephi/authme/api/v3/AuthMePlayer.java new file mode 100644 index 0000000000..4c64073b85 --- /dev/null +++ b/src/main/java/fr/xephi/authme/api/v3/AuthMePlayer.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.api.v3; + +import java.time.Instant; +import java.util.Optional; +import java.util.UUID; + +/** + * Read-only player info exposed in the AuthMe API. The data in this object is copied from the + * database and not updated afterwards. As such, it may become outdated if the player data changes + * in AuthMe. + * + * @see AuthMeApi#getPlayerInfo + */ +public interface AuthMePlayer { + + /** + * @return the case-sensitive name of the player, e.g. "thePlayer3030" - never null + */ + String getName(); + + /** + * Returns the UUID of the player as given by the server (may be offline UUID or not). + * The UUID is not present if AuthMe is configured not to store the UUID or if the data is not + * present (e.g. older record). + * + * @return player uuid, or empty optional if not available + */ + Optional getUuid(); + + /** + * Returns the email address associated with this player, or an empty optional if not available. + * + * @return player's email or empty optional + */ + Optional getEmail(); + + /** + * @return the registration date of the player's account - never null + */ + Instant getRegistrationDate(); + + /** + * Returns the IP address with which the player's account was registered. Returns an empty optional + * for older accounts, or if the account was registered by someone else (e.g. by an admin). + * + * @return the ip address used during the registration of the account, or empty optional + */ + Optional getRegistrationIpAddress(); + + /** + * Returns the last login date of the player. An empty optional is returned if the player never logged in. + * + * @return date the player last logged in successfully, or empty optional if not applicable + */ + Optional getLastLoginDate(); + + /** + * Returns the IP address the player last logged in with successfully. Returns an empty optional if the + * player never logged in. + * + * @return ip address the player last logged in with successfully, or empty optional if not applicable + */ + Optional getLastLoginIpAddress(); + +} diff --git a/src/main/java/fr/xephi/authme/api/v3/AuthMePlayerImpl.java b/src/main/java/fr/xephi/authme/api/v3/AuthMePlayerImpl.java new file mode 100644 index 0000000000..9ea0b643bb --- /dev/null +++ b/src/main/java/fr/xephi/authme/api/v3/AuthMePlayerImpl.java @@ -0,0 +1,93 @@ +package fr.xephi.authme.api.v3; + +import fr.xephi.authme.data.auth.PlayerAuth; + +import java.time.Instant; +import java.util.Optional; +import java.util.UUID; + +/** + * Implementation of {@link AuthMePlayer}. This implementation is not part of the API and + * may have breaking changes in subsequent releases. + */ +class AuthMePlayerImpl implements AuthMePlayer { + + private String name; + private UUID uuid; + private String email; + + private Instant registrationDate; + private String registrationIpAddress; + + private Instant lastLoginDate; + private String lastLoginIpAddress; + + AuthMePlayerImpl() { + } + + /** + * Maps the given player auth to an AuthMePlayer instance. Returns an empty optional if + * the player auth is null. + * + * @param playerAuth the player auth or null + * @return the mapped player auth, or empty optional if the argument was null + */ + static Optional fromPlayerAuth(PlayerAuth playerAuth) { + if (playerAuth == null) { + return Optional.empty(); + } + + AuthMePlayerImpl authMeUser = new AuthMePlayerImpl(); + authMeUser.name = playerAuth.getRealName(); + authMeUser.uuid = playerAuth.getUuid(); + authMeUser.email = nullIfDefault(playerAuth.getEmail(), PlayerAuth.DB_EMAIL_DEFAULT); + Long lastLoginMillis = nullIfDefault(playerAuth.getLastLogin(), PlayerAuth.DB_LAST_LOGIN_DEFAULT); + authMeUser.registrationDate = toInstant(playerAuth.getRegistrationDate()); + authMeUser.registrationIpAddress = playerAuth.getRegistrationIp(); + authMeUser.lastLoginDate = toInstant(lastLoginMillis); + authMeUser.lastLoginIpAddress = nullIfDefault(playerAuth.getLastIp(), PlayerAuth.DB_LAST_IP_DEFAULT); + return Optional.of(authMeUser); + } + + @Override + public String getName() { + return name; + } + + public Optional getUuid() { + return Optional.ofNullable(uuid); + } + + @Override + public Optional getEmail() { + return Optional.ofNullable(email); + } + + @Override + public Instant getRegistrationDate() { + return registrationDate; + } + + @Override + public Optional getRegistrationIpAddress() { + return Optional.ofNullable(registrationIpAddress); + } + + @Override + public Optional getLastLoginDate() { + return Optional.ofNullable( lastLoginDate); + } + + @Override + public Optional getLastLoginIpAddress() { + return Optional.ofNullable(lastLoginIpAddress); + } + + private static Instant toInstant(Long epochMillis) { + return epochMillis == null ? null : Instant.ofEpochMilli(epochMillis); + } + + private static T nullIfDefault(T value, T defaultValue) { + return defaultValue.equals(value) ? null : value; + } +} diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index ada52966af..7fe125717c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -6,6 +6,7 @@ import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.process.AsyncUserScheduler; import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.service.BukkitService; @@ -40,6 +41,9 @@ public class RegisterAdminCommand implements ExecutableCommand { @Inject private ValidationService validationService; + @Inject + private AsyncUserScheduler asyncUserScheduler; + @Override public void executeCommand(final CommandSender sender, List arguments) { // Get the player name and password @@ -54,7 +58,7 @@ public void executeCommand(final CommandSender sender, List arguments) { return; } - bukkitService.runTaskOptionallyAsync(() -> { + asyncUserScheduler.runTask(playerNameLowerCase, () -> { if (dataSource.isAuthAvailable(playerNameLowerCase)) { commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED); return; diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index 987338fa27..368385aa1c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -5,6 +5,7 @@ import fr.xephi.authme.data.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.message.MessageKey; +import fr.xephi.authme.process.AsyncUserScheduler; import fr.xephi.authme.service.BukkitService; import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.ValidationService; @@ -33,11 +34,14 @@ public class SetEmailCommand implements ExecutableCommand { @Inject private ValidationService validationService; + @Inject + private AsyncUserScheduler asyncUserScheduler; + @Override public void executeCommand(final CommandSender sender, List arguments) { // Get the player name and email address - final String playerName = arguments.get(0); - final String playerEmail = arguments.get(1); + String playerName = arguments.get(0); + String playerEmail = arguments.get(1); // Validate the email address if (!validationService.validateEmail(playerEmail)) { @@ -45,34 +49,32 @@ public void executeCommand(final CommandSender sender, List arguments) { return; } - bukkitService.runTaskOptionallyAsync(new Runnable() { - @Override - public void run() { - // Validate the user - PlayerAuth auth = dataSource.getAuth(playerName); - if (auth == null) { - commonService.send(sender, MessageKey.UNKNOWN_USER); - return; - } else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) { - commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR); - return; - } - - // Set the email address - auth.setEmail(playerEmail); - if (!dataSource.updateEmail(auth)) { - commonService.send(sender, MessageKey.ERROR); - return; - } + String lowercasePlayerName = playerName.toLowerCase(); + asyncUserScheduler.runTask(lowercasePlayerName, () -> { + // Validate the user + PlayerAuth auth = dataSource.getAuth(playerName); + if (auth == null) { + commonService.send(sender, MessageKey.UNKNOWN_USER); + return; + } else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) { + commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR); + return; + } - // Update the player cache - if (playerCache.getAuth(playerName) != null) { - playerCache.updatePlayer(auth); - } + // Set the email address + auth.setEmail(playerEmail); + if (!dataSource.updateEmail(auth)) { + commonService.send(sender, MessageKey.ERROR); + return; + } - // Show a status message - commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS); + // Update the player cache + if (playerCache.getAuth(playerName) != null) { + playerCache.updatePlayer(auth); } + + // Show a status message + commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS); }); } } diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index 1a41c52369..f0d7638e40 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -488,7 +488,7 @@ private boolean isInventoryWhitelisted(InventoryView inventory) { return false; } Set whitelist = settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES); - return whitelist.contains(ChatColor.stripColor(inventory.getTitle())); + return whitelist.contains(ChatColor.stripColor(inventory.getTitle()).toLowerCase()); } @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) diff --git a/src/main/java/fr/xephi/authme/process/AsyncUserScheduler.java b/src/main/java/fr/xephi/authme/process/AsyncUserScheduler.java new file mode 100644 index 0000000000..d245af8b6b --- /dev/null +++ b/src/main/java/fr/xephi/authme/process/AsyncUserScheduler.java @@ -0,0 +1,92 @@ +package fr.xephi.authme.process; + +import fr.xephi.authme.service.BukkitService; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import javax.inject.Inject; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.Function; + +/** + * Handles the queue of async tasks on a per-player basis. + */ +public class AsyncUserScheduler { + + @Inject + private BukkitService bukkitService; + + private KeyedSequentialScheduler asyncUserScheduler; + + AsyncUserScheduler() { + this.asyncUserScheduler = new KeyedSequentialScheduler<>(runnable -> + bukkitService.runTaskAsynchronously(runnable)); + } + + /** + * Adds a task to the player's async task queue. + * + * @param playerName the player name. + * @param runnable the task. + */ + public void runTask(String playerName, Runnable runnable) { + if (bukkitService.isUseAsyncTasks()) { + asyncUserScheduler.submit(playerName.toLowerCase(), runnable); + } else { + runnable.run(); + } + } + /** + * Adds a task to the player's async task queue. + * + * @param player the player. + * @param runnable the task. + */ + public void runTask(Player player, Runnable runnable) { + runTask(player.getName(), runnable); + } + + public class KeyedSequentialScheduler { + private Map executors; + private Function scheduler; + + public KeyedSequentialScheduler(Function scheduler) { + this.executors = new LinkedHashMap<>(); + this.scheduler = scheduler; + } + + public void submit(K key, Runnable runnable) { + executors.computeIfAbsent(key, k -> new SequentialExecutor(scheduler, () -> executors.remove(key))) + .submit(runnable); + } + } + + public class SequentialExecutor { + private Queue queue; + private Function scheduler; + private Runnable callback; + + private BukkitTask executor; + + public SequentialExecutor(Function scheduler, Runnable callback) { + this.queue = new LinkedBlockingQueue<>(); + this.scheduler = scheduler; + this.callback = callback; + } + + public void submit(Runnable task) { + queue.add(task); + if (executor == null || executor.isCancelled()) { + executor = scheduler.apply(() -> { + while (!queue.isEmpty()) { + queue.poll().run(); + } + callback.run(); + }); + } + } + } +} diff --git a/src/main/java/fr/xephi/authme/process/Management.java b/src/main/java/fr/xephi/authme/process/Management.java index 5260fed13b..e926944277 100644 --- a/src/main/java/fr/xephi/authme/process/Management.java +++ b/src/main/java/fr/xephi/authme/process/Management.java @@ -11,7 +11,6 @@ import fr.xephi.authme.process.register.executors.RegistrationMethod; import fr.xephi.authme.process.register.executors.RegistrationParameters; import fr.xephi.authme.process.unregister.AsynchronousUnregister; -import fr.xephi.authme.service.BukkitService; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -23,7 +22,7 @@ public class Management { @Inject - private BukkitService bukkitService; + private AsyncUserScheduler asyncUserScheduler; // Processes @Inject @@ -50,54 +49,58 @@ public class Management { public void performLogin(Player player, String password) { - runTask(() -> asynchronousLogin.login(player, password)); + runTask(player, () -> asynchronousLogin.login(player, password)); } public void forceLogin(Player player) { - runTask(() -> asynchronousLogin.forceLogin(player)); + runTask(player, () -> asynchronousLogin.forceLogin(player)); } public void performLogout(Player player) { - runTask(() -> asynchronousLogout.logout(player)); + runTask(player, () -> asynchronousLogout.logout(player)); } public

void performRegister(RegistrationMethod

variant, P parameters) { - runTask(() -> asyncRegister.register(variant, parameters)); + runTask(parameters.getPlayer(), () -> asyncRegister.register(variant, parameters)); } public void performUnregister(Player player, String password) { - runTask(() -> asynchronousUnregister.unregister(player, password)); + runTask(player, () -> asynchronousUnregister.unregister(player, password)); } public void performUnregisterByAdmin(CommandSender initiator, String name, Player player) { - runTask(() -> asynchronousUnregister.adminUnregister(initiator, name, player)); + runTask(name, () -> asynchronousUnregister.adminUnregister(initiator, name, player)); } public void performJoin(Player player) { - runTask(() -> asynchronousJoin.processJoin(player)); + runTask(player, () -> asynchronousJoin.processJoin(player)); } public void performQuit(Player player) { - runTask(() -> asynchronousQuit.processQuit(player)); + runTask(player, () -> asynchronousQuit.processQuit(player)); } public void performAddEmail(Player player, String newEmail) { - runTask(() -> asyncAddEmail.addEmail(player, newEmail)); + runTask(player, () -> asyncAddEmail.addEmail(player, newEmail)); } public void performChangeEmail(Player player, String oldEmail, String newEmail) { - runTask(() -> asyncChangeEmail.changeEmail(player, oldEmail, newEmail)); + runTask(player, () -> asyncChangeEmail.changeEmail(player, oldEmail, newEmail)); } public void performPasswordChange(Player player, String oldPassword, String newPassword) { - runTask(() -> asyncChangePassword.changePassword(player, oldPassword, newPassword)); + runTask(player, () -> asyncChangePassword.changePassword(player, oldPassword, newPassword)); } - public void performPasswordChangeAsAdmin(CommandSender sender, String playerName, String newPassword) { - runTask(() -> asyncChangePassword.changePasswordAsAdmin(sender, playerName, newPassword)); + public void performPasswordChangeAsAdmin(CommandSender sender, String name, String newPassword) { + runTask(name, () -> asyncChangePassword.changePasswordAsAdmin(sender, name, newPassword)); } - private void runTask(Runnable runnable) { - bukkitService.runTaskOptionallyAsync(runnable); + private void runTask(Player player, Runnable runnable) { + runTask(player.getName(), runnable); + } + + private void runTask(String playerName, Runnable runnable) { + asyncUserScheduler.runTask(playerName.toLowerCase(), runnable); } } diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java index 3db023118a..95541220c8 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -7,6 +7,7 @@ import fr.xephi.authme.output.ConsoleLoggerFactory; import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.permission.PlayerStatePermission; +import fr.xephi.authme.process.AsyncUserScheduler; import fr.xephi.authme.process.AsynchronousProcess; import fr.xephi.authme.process.login.AsynchronousLogin; import fr.xephi.authme.service.BukkitService; @@ -57,6 +58,9 @@ public class AsynchronousJoin implements AsynchronousProcess { @Inject private BukkitService bukkitService; + @Inject + private AsyncUserScheduler asyncUserScheduler; + @Inject private AsynchronousLogin asynchronousLogin; @@ -126,7 +130,7 @@ public void processJoin(final Player player) { // Run commands bukkitService.scheduleSyncTaskFromOptionallyAsyncTask( () -> commandManager.runCommandsOnSessionLogin(player)); - bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player)); + asyncUserScheduler.runTask(name, () -> asynchronousLogin.forceLogin(player)); return; } } else if (!service.getProperty(RegistrationSettings.FORCE)) { diff --git a/src/main/java/fr/xephi/authme/service/BukkitService.java b/src/main/java/fr/xephi/authme/service/BukkitService.java index 5e693d6f51..3d75393a30 100644 --- a/src/main/java/fr/xephi/authme/service/BukkitService.java +++ b/src/main/java/fr/xephi/authme/service/BukkitService.java @@ -350,4 +350,13 @@ public Optional isBungeeCordConfiguredForSpigot() { public String getIp() { return Bukkit.getServer().getIp(); } + + /** + * Returns if async tasks are enabled. + * + * @return true if async tasks are enabled. + */ + public boolean isUseAsyncTasks() { + return useAsyncTasks; + } } diff --git a/src/main/resources/messages/help_et.yml b/src/main/resources/messages/help_et.yml index 14791c1fc2..03a7021349 100644 --- a/src/main/resources/messages/help_et.yml +++ b/src/main/resources/messages/help_et.yml @@ -5,14 +5,14 @@ common: header: '==========[ AuthMeReloaded ABI ]==========' optional: 'Valikuline' - hasPermission: 'Sul on õigus' - noPermission: 'Pole õigust' + hasPermission: 'Sul on luba' + noPermission: 'Pole luba' default: 'Vaikimisi' result: 'Tulemus' defaultPermissions: - notAllowed: 'Pole õigust' + notAllowed: 'Pole luba' opOnly: 'Ainult operaatorid' - allowed: 'Õigus kõigil' + allowed: 'Luba kõigil' # ------------------------------------------------------- # Titles of the individual help sections @@ -23,7 +23,7 @@ section: description: 'Lühike kirjeldus' detailedDescription: 'Detailne kirjeldus' arguments: 'Argumendid' - permissions: 'Õigused' + permissions: 'Load' alternatives: 'Alternatiivid' children: 'Käsklused' diff --git a/src/main/resources/messages/help_eu.yml b/src/main/resources/messages/help_eu.yml new file mode 100644 index 0000000000..52fad80256 --- /dev/null +++ b/src/main/resources/messages/help_eu.yml @@ -0,0 +1,23 @@ +# Translation config for the AuthMe help, e.g. when /authme help or /authme help register is called + +# ------------------------------------------------------- +# List of texts used in the help section +common: + header: '==========[ AuthMeReloaded LAGUNTZA ]==========' + optional: 'Hautazkoa' + hasPermission: 'Baimena daukazu' + noPermission: 'Ez daukazu baimenik' + default: 'Lehenetsia' + result: 'Emaitza' + defaultPermissions: + notAllowed: 'Baimenik ez' + opOnly: 'OP bakarrik' + allowed: 'Edonor baimenduta' +section: + command: 'Komandoa' + description: 'Deskribapen laburra' + detailedDescription: 'Deskribapen xehakatua' + arguments: 'Argumentuak' + permissions: 'Baimenak' + alternatives: 'Alternatibak' + children: 'Komandoak' diff --git a/src/main/resources/messages/messages_br.yml b/src/main/resources/messages/messages_br.yml index 1ea30781b2..fd59f53839 100644 --- a/src/main/resources/messages/messages_br.yml +++ b/src/main/resources/messages/messages_br.yml @@ -4,16 +4,16 @@ # Lista de tags globais: # %nl% - Pula uma linha # %username% - Substitui pelo nome do jogador que está recebendo a mensagem -# %displayname% - Substitui o nickname (e cores) do jogador que está recebendo a mensagem +# %displayname% - Substitui pelo nickname (e cores) do jogador que está recebendo a mensagem # Registro registration: register_request: '&3Por favor, registre-se com o comando "/register "' command_usage: '&cUse: /register ' reg_only: '&4Somente usuários registrados podem entrar no servidor! Por favor visite www.seusite.com para se registrar!' - success: '&2Registrado com êxito!' - kicked_admin_registered: 'Um administrador registrou você. Por favor faça login novamente' - disabled: '&cO registro está desativado nesse servidor!' + success: '&2Registrado com sucesso!' + kicked_admin_registered: 'Um administrador registrou você. Por favor, faça login novamente' + disabled: '&cRegistrar-se está desativado neste servidor!' name_taken: '&cVocê já registrou este nome de usuário!' # Erros de senha ao registrar-se @@ -70,17 +70,17 @@ misc: # Mensagens de sessão session: valid_session: '&2Você deslogou recentemente, então sua sessão foi retomada!' - invalid_session: '&O seu IP foi alterado e sua sessão expirou!' + invalid_session: '&fO seu IP foi alterado e sua sessão expirou!' # Mensagens de erro ao entrar on_join_validation: - name_length: '&4Seu nome de usuário ou é muito curto ou muito longo!' + name_length: '&4Seu nome de usuário ou é muito curto ou é muito longo!' characters_in_name: '&4Seu nome de usuário contém caracteres inválidos. Caracteres permitidos: %valid_chars' - country_banned: '&4O seu país está banido neste servidor!' + country_banned: '&4O seu país está banido deste servidor!' not_owner_error: 'Você não é o proprietário da conta. Por favor, escolha outro nome!' kick_full_server: '&4O servidor está cheio, tente novamente mais tarde!' - same_nick_online: '&4O mesmo nome de usuário já está jogando no servidor!' - invalid_name_case: 'Você deve se juntar usando o nome de usuário %valid, não %invalid.' + same_nick_online: '&4Alguém com o mesmo nome de usuário já está jogando no servidor!' + invalid_name_case: 'Você deve entrar usando o nome de usuário %valid, não %invalid.' same_ip_online: 'Um jogador com o mesmo IP já está no servidor!' quick_command: 'Você usou o comando muito rápido! Por favor, entre no servidor e aguarde antes de usar um comando novamente.' @@ -92,7 +92,7 @@ email: old_email_invalid: '&cE-mail antigo inválido, tente novamente!' invalid: '&E-mail inválido, tente novamente!' added: '&2E-mail adicionado com sucesso!' - request_confirmation: '&cPor favor confirme seu endereço de e-mail!' + request_confirmation: '&cPor favor, confirme o seu endereço de e-mail!' changed: '&2E-mail alterado com sucesso!' email_show: '&2O seu endereço de e-mail atual é: &f%email' incomplete_settings: 'Erro: Nem todas as configurações necessárias estão definidas para o envio de e-mails. Entre em contato com um administrador.' @@ -107,7 +107,7 @@ email: # Recuperação de senha por e-mail recovery: - forgot_password_hint: '&3Esqueceu sua senha? Por favor, use o comando "/email recovery "' + forgot_password_hint: '&3Esqueceu a sua senha? Use o comando "/email recovery "' command_usage: '&cUse: /email recovery ' email_sent: '&2E-mail de recuperação enviado! Por favor, verifique sua caixa de entrada!' code: @@ -120,7 +120,7 @@ recovery: # Captcha captcha: usage_captcha: '&3Para iniciar sessão você tem que resolver um captcha, utilize o comando "/captcha %captcha_code"' - wrong_captcha: '&cCaptcha incorreto, por favor, escreva "/captcha %captcha_code" no chat!' + wrong_captcha: '&cCaptcha incorreto. Por favor, escreva "/captcha %captcha_code" no chat!' valid_captcha: '&2Captcha correto!' captcha_for_registration: 'Para se registrar você tem que resolver um código captcha, utilize o comando "/captcha %captcha_code"' register_captcha_valid: '&2Captcha correto! Agora você pode se registrar usando /register !' @@ -130,9 +130,9 @@ verification: code_required: '&3Esse comando é sensível e precisa de uma verificação via e-mail! Verifique sua caixa de entrada e siga as instruções do e-mail.' command_usage: '&cUse: /verification ' incorrect_code: '&cCódigo incorreto, utilize "/verification " com o código que você recebeu por e-mail!' - success: '&2Sua identidade foi verificada, agora você pode usar todos os comandos nessa sessão.' - already_verified: '&2Você já pode executar comandos sensíveis nessa sessão!' - code_expired: '&3Seu código expirou! Execute outro comando sensível para gerar outro código.' + success: '&2Sua identidade foi verificada, agora você pode usar todos os comandos durante esta sessão.' + already_verified: '&2Você já pode executar comandos sensíveis durante esta sessão!' + code_expired: '&3O seu código expirou! Execute outro comando sensível para gerar um outro código.' email_needed: '&3Para verificar sua identidade, você precisa vincular um e-mail à sua conta!' # Verificação em duas etapas diff --git a/src/main/resources/messages/messages_et.yml b/src/main/resources/messages/messages_et.yml index 3c388b7cd9..080f02bf85 100644 --- a/src/main/resources/messages/messages_et.yml +++ b/src/main/resources/messages/messages_et.yml @@ -5,21 +5,21 @@ # Registration registration: - disabled: '&cMängusisene registreerimine on välja lülitatud!' - name_taken: '&cSee kasutaja on juba registreeritud!' register_request: '&3Palun registreeri käsklusega: /register ' command_usage: '&cKasutus: /register ' - reg_only: '&4Vaid registreeritud mängijad saavad liituda serveriga! Külasta http://example.com enda kasutaja registreerimiseks!' - success: '&2Edukalt registreeritud!' + reg_only: '&4Vaid registreeritud mängijad saavad serveriga liituda! Enda kasutaja registreerimiseks külasta http://example.com!' kicked_admin_registered: 'Administraator registreeris su kasutaja, palun logi uuesti sisse.' + success: '&2Edukalt registreeritud!' + disabled: '&cMängusisene registreerimine on välja lülitatud!' + name_taken: '&cSee kasutaja on juba registreeritud!' # Password errors on registration password: match_error: '&cParoolid ei kattu, palun proovi uuesti!' - name_in_password: '&cSa ei saa kasutada oma kasutajanime paroolina, palun vali mõni teine parool.' + name_in_password: '&cSa ei saa oma kasutajanime paroolina kasutada, palun vali mõni teine parool.' unsafe_password: '&cSee parool ei ole turvaline, palun vali mõni teine parool.' - forbidden_characters: '&4Su parool sisaldab keelatud tähemärke. Lubatud tähemärgid: %valid_chars' - wrong_length: '&cSu parool on liiga pikk või lühike, palun vali mõni teine parool.' + forbidden_characters: '&4Sinu parool sisaldab keelatud tähemärke. Lubatud tähemärgid: %valid_chars' + wrong_length: '&cSinu parool on liiga pikk või lühike, palun vali mõni teine parool.' # Login login: @@ -27,80 +27,79 @@ login: wrong_password: '&cVale parool!' success: '&2Edukalt sisselogitud!' login_request: '&cPalun logi sisse kasutades käsklust: /login ' - timeout_error: '&4Sisselogimiseks antud aeg on läbi, palun proovi uuesti!' + timeout_error: '&4Sisselogimiseks antud aeg on läbi ning sind on serverist välja visatud, palun proovi uuesti!' # Errors error: - denied_command: '&cSelle käskluse kasutamiseks pead sisse logima!' - denied_chat: '&cRääkimiseks pead sisse logima!' unregistered_user: '&cSee kasutaja ei ole registreeritud!' + denied_command: '&cSelle käskluse kasutamiseks pead olema sisselogitud!' + denied_chat: '&cVestlemiseks pead olema sisselogitud!' not_logged_in: '&cSa ei ole sisselogitud!' - no_permission: '&4Sul ei ole õigust selle käskluse kasutamiseks.' - unexpected_error: '&4Süsteemis tekkis viga, teata sellest administraatorile!' - max_registration: '&cSu IP aadressile on registreeritud liiga palju kasutajaid! (%reg_count/%max_acc %reg_names)' + tempban_max_logins: '&cSind on ajutiselt serverist blokeeritud, kuna sisestasid mitu korda vale parooli.' + max_registration: '&cSinu IP-aadressile on registreeritud liiga palju kasutajaid! (%reg_count/%max_acc %reg_names)' + no_permission: '&4Sul puudub selle käskluse kasutamiseks luba.' + unexpected_error: '&4Esines ootamatu tõrge, palun teavita administraatorit!' + kick_for_vip: '&3VIP-mängija liitus serveriga ajal, mil see oli täis!' logged_in: '&cSa oled juba sisselogitud!' - kick_for_vip: '&3VIP mängija liitus serveriga ajal, mil see oli täis!' - # TODO kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' - tempban_max_logins: '&cSind blokeeriti ajutiselt serverist, sest sisestasid mitu korda vale parooli.' + kick_unresolved_hostname: '&cEsines tõrge: mängija hostinimi on lahendamata!' # AntiBot antibot: - kick_antibot: 'AntiBot kaitse sisse lülitatud! Pead ootama mõne minuti enne kui serveriga liituda saad.' - auto_enabled: '&4[AntiBotKaitse] AntiBot sisselülitatud!' - auto_disabled: '&2[AntiBotKaitse] AntiBot välja lülitatud peale %m minutit!' + kick_antibot: 'AntiBot-kaitse sisse lülitatud! Pead ootama mõne minuti enne kui serveriga liituda saad.' + auto_enabled: '&4[AntiBotTeenus] AntiBot sisselülitatud!' + auto_disabled: '&2[AntiBotTeenus] AntiBot välja lülitatud peale %m minutit!' -# Unregister unregister: success: '&cKasutaja edukalt kustutatud!' command_usage: '&cKasutus: /unregister ' # Other messages misc: - account_not_activated: '&cSu konto ei ole veel aktiveeritud, kontrolli oma meili!' - password_changed: '&2Parool vahetatud!' - logout: '&2Edukalt välja logitud!' - reload: '&2Andmebaas edukalt laetud!' - usage_change_password: '&cKasutus: /changepassword ' accounts_owned_self: 'Sa omad %count kontot:' accounts_owned_other: 'Mängijal %name on %count kontot:' + account_not_activated: '&cSinu konto ei ole veel aktiveeritud, kontrolli oma meili!' + password_changed: '&2Parool edukalt vahetatud!' + logout: '&2Edukalt välja logitud!' + reload: '&2Seadistused ning andmebaas on edukalt taaslaaditud!' + usage_change_password: '&cKasutus: /changepassword ' # Session messages session: + invalid_session: '&cSinu IP-aadress muutus, seega sinu sessioon aegus!' valid_session: '&2Sisse logitud sessiooni jätkumise tõttu.' - invalid_session: '&cSu IP aadress muutus mistõttu sinu sessioon aegus!' # Error messages when joining on_join_validation: - same_ip_online: 'Sama IP aadressiga mängija juba mängib!' - same_nick_online: '&4Sama kasutaja on juba ühendatud serveriga!' - name_length: '&4Su kasutajanimi on liiga pikk või lühike!' - characters_in_name: '&4Su kasutajanimi sisaldab keelatud tähemärke. Lubatud tähemärgid: %valid_chars' - kick_full_server: '&4Server täis, proovi uuesti!' - country_banned: '&4Sinu riigist ei ole võimalik ühenduda sellesse serverisse!' - not_owner_error: 'Sa ei ole selle kasutaja omanik. Vali teine nimi!!' + name_length: '&4Sinu kasutajanimi on liiga pikk või liiga lühike!' + characters_in_name: '&4Sinu kasutajanimi sisaldab keelatud tähemärke. Lubatud tähemärgid: %valid_chars' + country_banned: '&4Sinu riigist ei ole võimalik sellesse serverisse ühenduda!' + not_owner_error: 'Sa ei ole selle konto omanik. Vali teine nimi!' + kick_full_server: '&4Server on täis, proovi hiljem uuesti!' + same_nick_online: '&4Sama kasutaja on juba serveriga ühendatud!' invalid_name_case: 'Sa peaksid liituma nimega %valid, mitte nimega %invalid.' - quick_command: 'Sa kasutasid käsklust liiga kiiresti! Palun liitu serveriga ja oota kauem enne kui käsklust kasutad.' + same_ip_online: 'Sama IP-aadressiga mängija juba mängib!' + quick_command: 'Sa kasutasid käsklust liiga kiiresti! Palun liitu serveriga uuesti ning oota enne mõne käskluse kasutamist kauem.' # Email email: - add_email_request: '&3Palun seo oma kasutajaga meiliaadress kasutades käsklust: /email add ' usage_email_add: '&cKasutus: /email add ' usage_email_change: '&cKasutus: /email change ' - new_email_invalid: '&cUus meiliaadress on vale, proovi uuesti!' - old_email_invalid: '&cVana meiliaadress on vale, proovi uuesti!' - invalid: '&cVale meiliaadress, proovi uuesti!' + new_email_invalid: '&cUus meiliaadress on sobimatu, proovi uuesti!' + old_email_invalid: '&cVana meiliaadress on sobimatu, proovi uuesti!' + invalid: '&cSobimatu meiliaadress, proovi uuesti!' added: '&2Meiliaadress edukalt lisatud!' - add_not_allowed: '&cMeiliaadressi lisamine ei ole lubatud.' request_confirmation: '&cPalun kinnita oma meiliaadress!' changed: '&2Meiliaadress edukalt muudetud!' - change_not_allowed: '&cMeiliaadressi muutmine ei ole lubatud.' - email_show: '&2Su praegune meiliaadress on: &f%email' - no_email_for_account: '&2Selle kasutajaga ei ole seotud ühtegi meiliaadressi.' + email_show: '&2Sinu praegune meiliaadress on: &f%email' + incomplete_settings: 'Viga: meili saatmiseks pole kõik vajalikud seaded seadistatud. Teata sellest administraatorit.' already_used: '&4See meiliaadress on juba kasutuses!' - incomplete_settings: 'Viga: meili saatmiseks pole kõik vajalikud seaded seadistatud. Teata sellest administraatorile.' - send_failure: 'Meili ei õnnestunud saata. Teata sellest administraatorile.' + send_failure: 'Meili ei õnnestunud saata. Teata sellest administraatorit.' + no_email_for_account: '&2Selle kasutajaga ei ole seotud ühtegi meiliaadressi.' + add_email_request: '&3Palun seo oma kasutajaga meiliaadress kasutades käsklust: /email add ' change_password_expired: 'Selle käsklusega ei saa sa enam parooli muuta.' email_cooldown_error: '&cMeil on juba saadetud. Sa pead ootama %time enne kui saad küsida uue saatmist.' + add_not_allowed: '&cMeiliaadressi lisamine ei ole lubatud.' + change_not_allowed: '&cMeiliaadressi muutmine ei ole lubatud.' # Password recovery by email recovery: @@ -109,49 +108,49 @@ recovery: email_sent: '&2Konto taastamiseks vajalik meil saadetud! Vaata oma postkasti.' code: code_sent: 'Konto taastamise kood on saadetud!' - incorrect: 'Kood vale! Sul on %count katset jäänud.' + incorrect: 'Kood on vale! Sul on %count katset jäänud.' tries_exceeded: 'Sul on katsed otsas. Kasuta käsklust "/email recovery [email]" uue koodi saamiseks.' correct: 'Kood õigesti sisestatud!' - change_password: 'Palun kasuta käsklust /email setpassword parooli muutmiseks.' + change_password: 'Palun kasuta parooli muutmiseks käsklust /email setpassword .' # Captcha captcha: - usage_captcha: '&3Sisselogimiseks lahenda captcha käsklusega: /captcha %captcha_code' - wrong_captcha: '&cVale captcha, kasuta käsklust "/captcha %captcha_code"!' - valid_captcha: '&2Captcha lahendatud!' - captcha_for_registration: 'Registreerimiseks lahenda captcha kasutades käsklust: /captcha %captcha_code' - register_captcha_valid: '&2Captcha lahendatud! Võid nüüd registreerida kasutades käsklust /register' + usage_captcha: '&3Sisselogimiseks lahenda robotilõks käsklusega: /captcha %captcha_code' + wrong_captcha: '&cVale robotilõks, kasuta käsklust "/captcha %captcha_code"!' + valid_captcha: '&2Robotilõks lahendatud!' + captcha_for_registration: 'Registreerimiseks lahenda robotilõks kasutades käsklust: /captcha %captcha_code' + register_captcha_valid: '&2Robotilõks lahendatud! Võid nüüd registreerida kasutades käsklust /register' # Verification code verification: code_required: '&3See käsklus on ohtlik mistõttu saatsime sulle meili. Kontrolli oma meili ja järgi saadetud meili juhiseid.' command_usage: '&cKasutus: /verification ' incorrect_code: '&cVale kood, palun kasuta käsklust "/verification " koodiga, mille saatsime sulle meilile.' - success: '&2Konto kinnitatud!' + success: '&2Sinu identiteet on kinnitatud! Sa saad nüüd praeguse sessiooni jal kasutada kõiki käsklusi.' already_verified: '&2Sa juba saad kasutada kõiki ohtlikke käsklusi!' - code_expired: '&3Kood aegunud! Kasuta mõnda ohtlikku käsklust, et saada uus kood!' + code_expired: '&3Kood on aegunud! Kasuta mõnda ohtlikku käsklust, et saada uus kood!' email_needed: '&3Konto kinnitamiseks pead siduma oma kontoga enda meiliaadressi!' -# Time units -time: - second: 'sekund' - seconds: 'sekundit' - minute: 'minut' - minutes: 'minutit' - hour: 'tund' - hours: 'tundi' - day: 'päev' - days: 'päeva' - # Two-factor authentication two_factor: code_created: '&2Sinu privaatne kood on %code. Sa saad selle skännida aadressil %url' confirmation_required: 'Palun kinnita oma kaheastmeline autentimise kood käsklusega /2fa confirm ' code_required: 'Palun sisesta kaheastmeline autentimise kood kasutades /2fa code ' already_enabled: 'Kaheastmeline autentimine on juba sisselülitatud!' - enable_error_no_code: '2fa võtit ei ole genereeritud või on see aegunud. Kasuta käsklust /2fa add' + enable_error_no_code: '2FA võtit ei ole genereeritud või on see aegunud. Kasuta käsklust /2fa add' enable_success: 'Kaheastmeline autentimine edukalt sisselülitatud!' enable_error_wrong_code: 'Vale kood või kood on aegunud. Kasuta käsklust /2fa add' not_enabled_error: 'Kaheastmeline autentimine ei ole su kontol sisse lülitatud. Kasuta käsklust /2fa add' removed_success: 'Sinu kontolt on edukalt eemaldatud kaheastmeline autentimine.' invalid_code: 'Vale kood!' + +# Time units +time: + second: 'sekund' + seconds: 'sekundit' + minute: 'minut' + minutes: 'minutit' + hour: 'tund' + hours: 'tundi' + day: 'päev' + days: 'päeva' diff --git a/src/main/resources/messages/messages_eu.yml b/src/main/resources/messages/messages_eu.yml index a32386d7ee..b3b6b665e9 100644 --- a/src/main/resources/messages/messages_eu.yml +++ b/src/main/resources/messages/messages_eu.yml @@ -5,153 +5,153 @@ # Registration registration: - disabled: '&cErregistroa desgaitua' - name_taken: '&cErabiltzailea dagoeneko erregistratua' - register_request: '&cMesedez erabili "/register pasahitza pasahitza" erregistratzeko' - command_usage: '&cErabili: /register pasahitza pasahitza' - reg_only: '&fErregistratuako erabiltzaileak bakarrik! Mesedez bisitatu http://example.com erregistratzeko' - success: '&cOndo erregistratu zara!' - # TODO kicked_admin_registered: 'An admin just registered you; please log in again' + disabled: '&cIzen ematea itxita dago!' + name_taken: '&cDagoeneko badago erabiltzaile izen hori duen norbait.' + register_request: '&cMesedez erabili "/register " izena emateko' + command_usage: '&cErabilera: /register ' + reg_only: '&fIzena eman duten jokalariak bakarrik sartu daitezke! Mesedez, eman izena https://example.com webgunean' + success: '&cEskerrik asko izena emateagatik!' + kicked_admin_registered: 'Administratzaile batek izena eman dizu, mesedez irten eta sartu zerbitzaritik.' # Password errors on registration password: - match_error: '&fPasahitzak ez datoz bat' - # TODO name_in_password: '&cYou can''t use your name as password, please choose another one...' - # TODO unsafe_password: '&cThe chosen password isn''t safe, please choose another one...' - # TODO forbidden_characters: '&4Your password contains illegal characters. Allowed chars: %valid_chars' + match_error: '&fBi pasahitzak ez datoz bat' + name_in_password: '&cPasahitza eta erabiltzaile izena ezin dira berdinak izan. Mesedez, aukeratu beste pasahitz bat...' + unsafe_password: '&cAukeratutako pasahitza ez da segurua.Mesedez, aukeratu beste bat...' + forbidden_characters: '&4Pasahitzak ondorengo karaktereak bakarrik izan ditzake: %valid_chars' wrong_length: '&fZure pasahitza motzegia edo luzeegia da' # Login login: - command_usage: '&cErabili: /login pasahitza' + command_usage: '&cErabilera: /login pasahitza' wrong_password: '&cPasahitz okerra' - success: '&cOngi etorri!' + success: '&cSaioa hasi duzu!' login_request: '&cMesedez erabili "/login pasahitza" saioa hasteko' - timeout_error: '&fDenbora gehiegi egon zara saioa hasi gabe' + timeout_error: '&fDenbora gehiegi egon zara saioa hasi gabe.' # Errors error: - # TODO denied_command: '&cIn order to use this command you must be authenticated!' - # TODO denied_chat: '&cIn order to chat you must be authenticated!' - unregistered_user: '&cErabiltzailea ez dago erregistratuta' - not_logged_in: '&cSaioa hasi gabe!' - no_permission: '&cBaimenik ez' - unexpected_error: '&fErrorea; Mesedez jarri kontaktuan administratzaile batekin' - max_registration: '&fKontuko 2 erabiltzaile bakarrik izan ditzakezu' - logged_in: '&cDagoeneko saioa hasita!' - kick_for_vip: '&cVIP erabiltzaile bat sartu da zerbitzaria beteta zegoenean!' - # TODO kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' - # TODO tempban_max_logins: '&cYou have been temporarily banned for failing to log in too many times.' + denied_command: '&cHori egiteko ezinbestekoa da saioa hastea!' + denied_chat: '&cTxatean hitz egiteko ezinbestekoa da saioa hastea!' + unregistered_user: '&cErabiltzaileak ez du izena eman!' + not_logged_in: '&cEz duzu saioa hasi!' + no_permission: '&cEz daukazu baimenik' + unexpected_error: '&fUstekabeko errore bat gertatu da. Mesedez jarri harremanetan administratzaile batekin.' + max_registration: '&fKonexioko gehienezko erabiltzaile kopurua gainditu duzu (%reg_count/%max_acc %reg_names)' + logged_in: '&cDagoeneko saioa hasita duzu!' + kick_for_vip: '&cVIP erabiltzaile bati lekua egiteko kanporatua izan zara!' + kick_unresolved_hostname: '&cErrore bat geratu da: ezin izan da erabiltzailearen ostalari izena lortu!' + tempban_max_logins: '&cDenbora baterako kanporatua izan zara, pasahitza behin baino gehiagotan gaizki sartzeagatik.' # AntiBot antibot: - # TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.' - # TODO auto_enabled: '&4[AntiBotService] AntiBot enabled due to the huge number of connections!' - # TODO auto_disabled: '&2[AntiBotService] AntiBot disabled after %m minutes!' + kick_antibot: 'AntiBot babesa aktibatuta dago! Minutu batzuk itxaron beharko dituzu berriro sartu aurretik.' + auto_enabled: '&4[AntiBotZerbitzua] AntiBot babesa aktibatu da konexio kopurua handia delako!' + auto_disabled: '&2[AntiBotZerbitzua] AntiBot babesa desaktibatu da %m minutuz martxan egon ondoren!' # Unregister unregister: - success: '&cZure erregistroa ezabatu duzu!' - command_usage: '&cErabili: /unregister password' + success: '&cZure kontua ezabatu duzu!' + command_usage: '&cErabilera: /unregister ' # Other messages misc: - account_not_activated: '&fZure kontua aktibatu gabe dago, konfirmatu zure emaila!' - password_changed: '&cPasahitza aldatu duzu!' - logout: '&cAtera zara' - reload: '&fConfiguration and database has been reloaded' - usage_change_password: '&fErabili: /changepassword pasahitzZaharra pasahitzBerria' - # TODO accounts_owned_self: 'You own %count accounts:' - # TODO accounts_owned_other: 'The player %name has %count accounts:' + account_not_activated: '&fZure kontua aktibatu gabe dago. Mesedez, berretsi zure posta elektronikoa!' + password_changed: '&cPasahitza ondo aldatu duzu!' + logout: '&cSaioa itxi duzu' + reload: '&fEzarpenak eta datu-basea berrabiarazi dira' + usage_change_password: '&fErabilera: /changepassword ' + accounts_owned_self: '%count kontu dituzu:' + accounts_owned_other: '%name erabiltzaileak %count kontu ditu:' # Session messages session: - valid_session: '&cSession login' - # TODO invalid_session: '&cYour IP has been changed and your session data has expired!' + valid_session: '&cSesioa mantendu eta beraz ez daukazu saioa hasi beharrik.' + invalid_session: '&cZure IP helbidea aldatu da, eta horregatik zure sesioa iraungi da!' # Error messages when joining on_join_validation: - # TODO same_ip_online: 'A player with the same IP is already in game!' - same_nick_online: '&fZure izen berdina duen erabiltzaile bat zerbitzarian jolasten dago' + same_ip_online: 'IP helbide bera duen beste erabiltzaile bat dago zerbitzarian!' + same_nick_online: '&fErabiltzaile izen bera duen erabailtzaile bat dago zerbitzarian' name_length: '&cZure erabiltzaile izena motzegia edo luzeegia da' - characters_in_name: '&cZure erabiltzaileak karaktere debekatuak ditu. Karaktere onartuak: %valid_chars' - kick_full_server: '&cZerbitzaria beteta dago, Barkatu!' - country_banned: '[AuthMe] Zure herrialdea blokeatuta dago zerbitzari honetan' - # TODO not_owner_error: 'You are not the owner of this account. Please choose another name!' - # TODO invalid_name_case: 'You should join using username %valid, not %invalid.' - # TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.' + characters_in_name: '&cZure erabiltzaileak debekatutako karaktereak ditu. Ondorengoak bakarrik onartzen ditugu: %valid_chars' + kick_full_server: '&cZerbitzaria beteta dago. Sentitzen dugu!' + country_banned: 'Zure herrialdetik ezin zara zerbitzari honetan sartu' + not_owner_error: 'Kontu hau ez da zurea! Erabili beste bat!' + invalid_name_case: '%valid erabiltzailea erabili beharko duzu, ez %invalid.' + quick_command: 'Komandoa azkarregi exekutatu duzu! Mesdez, sartu zerbitzarian berriro eta itxaron pixka bat ezer idatzi aurretik.' # Email email: - add_email_request: '&cMesedez gehitu zure emaila : /email add yourEmail confirmEmail' - usage_email_add: '&fErabili: /email add ' - usage_email_change: '&fErabili: /email change ' - new_email_invalid: '[AuthMe] Email okerra!' - old_email_invalid: '[AuthMe] Email zaharra okerra!' - invalid: '[AuthMe] Email okerrea' - added: '[AuthMe] Emaila gehitu duzu !' - # TODO add_not_allowed: '&cAdding email was not allowed' - request_confirmation: '[AuthMe] Konfirmatu zure emaila !' - changed: '[AuthMe] Emaila aldatua!' - # TODO change_not_allowed: '&cChanging email was not allowed' - # TODO email_show: '&2Your current email address is: &f%email' - # TODO no_email_for_account: '&2You currently don''t have email address associated with this account.' - # TODO already_used: '&4The email address is already being used' - # TODO incomplete_settings: 'Error: not all required settings are set for sending emails. Please contact an admin.' - # TODO send_failure: 'The email could not be sent. Please contact an administrator.' - # TODO change_password_expired: 'You cannot change your password using this command anymore.' - # TODO email_cooldown_error: '&cAn email was already sent recently. You must wait %time before you can send a new one.' + add_email_request: '&cMesedez, sartu zure posta elektroniko helbidea : /email add ' + usage_email_add: '&fErabilera: /email add ' + usage_email_change: '&fErabilera: /email change ' + new_email_invalid: 'Helbide berria okerra da!' + old_email_invalid: 'Lehengo helbidea ez dator bat!' + invalid: 'Helbide okerra' + added: 'Helbidea ondo sartu duzu' + add_not_allowed: '&cEzin duzu posta helbiderik sartu' + request_confirmation: 'Berretsi zure posta helbidea!' + changed: 'Posta helbidea ondo aldatu duzu' + change_not_allowed: '&cEzin duzu posta helbidea aldatu' + email_show: '&2Zure posta helbidea ondorengoa da: &f%email' + no_email_for_account: '&2Ez daukazu posta helbiderik kontu honetara lotuta.' + already_used: '&4Posta helbide hori dagoeneko badarabil norbaitek' + incomplete_settings: 'Errorea: posta elektronikoak bidaltzeko ezparpen guztiak ez daude konfiguratu. Mesedez, jarri harremanetan administratzaile batekin.' + send_failure: 'Ezin izan da mezua bidali. Mesedez, jarri harremanetan administratzaile batekin.' + change_password_expired: 'Pasahitza aldatzeko denbora iraungi da.' + email_cooldown_error: '&cMezu bat bidali dizugu duela denbora gutxik. %time itxaron behar duzu berriro bidaltzeko eskatu aurretik.' # Password recovery by email recovery: - forgot_password_hint: '&cPasahitza ahaztu duzu? Erabili /email recovery ' - command_usage: '&fErabili: /email recovery ' - email_sent: '[AuthMe] Berreskuratze emaila bidalita !' + forgot_password_hint: '&cPasahitza ahaztu duzu? Berreskuratzeko erabili /email recovery ' + command_usage: '&fErabili: /email recovery ' + email_sent: 'Berreskuratze mezua bidali dizugu. Mesedez begiratu sarrera ontzia!' code: - # TODO code_sent: 'A recovery code to reset your password has been sent to your email.' - # TODO incorrect: 'The recovery code is not correct! You have %count tries remaining.' - # TODO tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.' - # TODO correct: 'Recovery code entered correctly!' - # TODO change_password: 'Please use the command /email setpassword to change your password immediately.' + code_sent: 'Pasahitza berreskuratzeko kode bat bidali dizugu zure posta elektronikora.' + incorrect: 'Berreskuratze kodea ez da zuzena! %count saiakera dituzu.' + tries_exceeded: 'Berreskuratze kodea sartzeko gehienezko saiakera kopurua gainditu duzu. Erabili "/email recovery [helbidea]" berri bat jasotzeko.' + correct: 'Kode zuzena!' + change_password: 'Mesedez, erabili "/email setpassword pasahitza aldatzeko.' # Captcha captcha: - # TODO usage_captcha: '&3To log in you have to solve a captcha code, please use the command: /captcha %captcha_code' - # TODO wrong_captcha: '&cWrong captcha, please type "/captcha %captcha_code" into the chat!' - # TODO valid_captcha: '&2Captcha code solved correctly!' - # TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code' - # TODO register_captcha_valid: '&2Valid captcha! You may now register with /register' + usage_captcha: '&3Sartzeko captcha asmatu beharko duzu. Mesedez erabaili /captcha %captcha_code' + wrong_captcha: '&cCaptacha okerra, mesedez, idatzi "/captcha %captcha_code" txatean!' + valid_captcha: '&2Captcha asmatu duzu!' + captcha_for_registration: 'Izena emateko captcha asmatu beharko duzu, mesedez erabili ondorengo komandoa: /captcha %captcha_code' + register_captcha_valid: '&2Captcha zuzena! Orain izena eman dezakezu /register erabilita' # Verification code verification: - # TODO code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.' - # TODO command_usage: '&cUsage: /verification ' - # TODO incorrect_code: '&cIncorrect code, please type "/verification " into the chat, using the code you received by email' - # TODO success: '&2Your identity has been verified! You can now execute all commands within the current session!' - # TODO already_verified: '&2You can already execute every sensitive command within the current session!' - # TODO code_expired: '&3Your code has expired! Execute another sensitive command to get a new code!' - # TODO email_needed: '&3To verify your identity you need to link an email address with your account!!' + code_required: '&3Komando hori babestuta dago, eta horregatik eposta berrespena beharrazkoa da! Begiratu zure sarrera ontzia, eta jarraitu bertan adierazitako pausoak.' + command_usage: '&cErabilera: /verification ' + incorrect_code: '&cKode okerra, mesedez idatzi "/verification " txatean, postan jaso duzun kodea erabilita' + success: '&2Zure identitatea berretsi duzu! Orain komando babestuak erabiltzeko baimena daukazu sesioak irauten duen bitartean!' + already_verified: '&2Dagoeneko badaukazu komando babestuak erabiltzeko baimena sesio honek irauten duen bitartean!' + code_expired: '&3Kodea iraungi egin da! Exekutatu beste komando babestu bat kode berri bat lortzeko!' + email_needed: '&3Zure identitatea berresteko beharrezkoa da zure kontuan posta elektronikoa konfiguratuta izatea!!' # Time units time: - # TODO second: 'second' - # TODO seconds: 'seconds' - # TODO minute: 'minute' - # TODO minutes: 'minutes' - # TODO hour: 'hour' - # TODO hours: 'hours' - # TODO day: 'day' - # TODO days: 'days' + second: 'segundu' + seconds: 'segundu' + minute: 'minutu' + minutes: 'minutu' + hour: 'ordu' + hours: 'ordu' + day: 'egun' + days: 'egun' # Two-factor authentication two_factor: - # TODO code_created: '&2Your secret code is %code. You can scan it from here %url' - # TODO confirmation_required: 'Please confirm your code with /2fa confirm ' - # TODO code_required: 'Please submit your two-factor authentication code with /2fa code ' - # TODO already_enabled: 'Two-factor authentication is already enabled for your account!' - # TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add' - # TODO enable_success: 'Successfully enabled two-factor authentication for your account' - # TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add' - # TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add' - # TODO removed_success: 'Successfully removed two-factor auth from your account' - # TODO invalid_code: 'Invalid code!' + code_created: '&2Zure kode sekretua %code da. Hemen eskaneatu dezakezu: %url' + confirmation_required: 'Mesedez, berretsi kodea ondorengoa erabilita: /2fa confirm ' + code_required: 'Mesedez, bidali zure bi faktoreko autentikazio kodea ondorengoa erabilita: /2fa code ' + already_enabled: 'Dagoeneko badaukazu bi faktoreko autentikazioa aktibatuta!' + enable_error_no_code: 'Ez duzu 2fa koderik sortu, edo iraungita dago. Mesedez, erabili /2fa add' + enable_success: '2 faktoreko autentikazioa aktibatu duzu' + enable_error_wrong_code: 'Kode okerra, edo iraungita dago. Mesedez erabili /2fa add' + not_enabled_error: 'Ez duzu 2 faktore autentikazioa konfiguratu. Erabaili /2fa add' + removed_success: '2 faktoreko autentikazioa desaktibatu duzu' + invalid_code: 'Kode okerra!' diff --git a/src/main/resources/messages/messages_fr.yml b/src/main/resources/messages/messages_fr.yml index cfcf67b222..4e2085db58 100644 --- a/src/main/resources/messages/messages_fr.yml +++ b/src/main/resources/messages/messages_fr.yml @@ -6,7 +6,7 @@ # %username% - Affiche le pseudo du joueur recevant le message. # %displayname% - Affiche le pseudo, avec couleurs, du joueur recevant le message. -# Registration +# Enregistrement registration: disabled: '&cL''inscription est désactivée.' name_taken: '&cUtilisateur déjà inscrit.' @@ -16,7 +16,7 @@ registration: success: '&aInscription effectuée !' kicked_admin_registered: 'Un admin vient de vous inscrire, veuillez vous reconnecter.' -# Password errors on registration +# Erreur de mot de passe lors de l'enregistrement password: match_error: '&cLe mot de passe de confirmation ne correspond pas.' name_in_password: '&cVous ne pouvez pas utiliser votre pseudo comme mot de passe.' @@ -24,7 +24,7 @@ password: forbidden_characters: '&cVotre mot de passe contient des caractères non autorisés. Caractères permis : %valid_chars' wrong_length: '&cVotre mot de passe est trop court ou trop long !' -# Login +# Identification login: command_usage: '&cUsage: /login ' wrong_password: '&cMauvais mot de passe !' @@ -32,7 +32,7 @@ login: login_request: '&cPour vous identifier, utilisez "/login "' timeout_error: 'Vous avez été expulsé car vous êtes trop lent pour vous enregistrer/identifier !' -# Errors +# Erreurs error: denied_command: '&cVous devez être connecté pour pouvoir utiliser cette commande.' denied_chat: '&cVous devez être connecté pour pouvoir écrire dans le chat.' @@ -43,7 +43,7 @@ error: max_registration: 'Vous avez atteint la limite d''inscription !%nl%&cVous avez %reg_count sur %max_acc : %reg_names' logged_in: '&aVous êtes déjà connecté.' kick_for_vip: 'Un joueur VIP a rejoint le serveur à votre place (serveur plein).' - # TODO kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' + kick_unresolved_hostname: '&cUne erreur est apparue : nom d''hôte non identifié !' tempban_max_logins: '&cVous êtes temporairement banni suite à plusieurs échecs de connexions !' # AntiBot @@ -52,12 +52,12 @@ antibot: auto_enabled: 'L''AntiBot a été activé automatiquement à cause de nombreuses connexions !' auto_disabled: 'L''AntiBot a été désactivé automatiquement après %m minutes, espérons que l''invasion se soit arrêtée !' -# Unregister +# Dé-enregistrement unregister: success: '&aCompte supprimé !' command_usage: '&cPour supprimer votre compte, utilisez "/unregister "' -# Other messages +# Autres messages misc: account_not_activated: '&fCe compte n''est pas actif, consultez vos mails !' password_changed: '&aMot de passe changé avec succès !' @@ -67,12 +67,12 @@ misc: accounts_owned_self: 'Vous avez %count comptes:' accounts_owned_other: 'Le joueur %name a %count comptes:' -# Session messages +# Session session: valid_session: '&aVous avez été automatiquement connecté !' invalid_session: 'Session expirée suite à un changement d''IP.' -# Error messages when joining +# Erreurs lors d'une tentative connexion on_join_validation: same_ip_online: 'Un joueur avec la même adresse IP joue déjà !' same_nick_online: 'Un joueur ayant le même pseudo est déjà connecté.' @@ -105,7 +105,7 @@ email: change_password_expired: 'Vous ne pouvez pas changer votre mot de passe avec cette commande.' email_cooldown_error: '&cUn mail de récupération a déjà été envoyé récemment. Veuillez attendre %time pour le demander de nouveau.' -# Password recovery by email +# Récupération de mot de passe par mail recovery: forgot_password_hint: '&cVous avez oublié votre Mot de Passe? Utilisez "/email recovery "' command_usage: '&fUsage: /email recovery ' @@ -125,7 +125,7 @@ captcha: captcha_for_registration: 'Avant de vous inscrire, veuillez rentrer un captcha en faisant "/captcha %captcha_code"' register_captcha_valid: '&aCaptcha validé! Vous pouvez maintenant vous inscrire.' -# Verification code +# Code de vérification verification: code_required: '&cCette commande est sensible, elle nécessite donc une confirmation par email.%nl%&cVeuillez suivre les instructions qui viennent de vous être envoyées par email.' command_usage: '&cUsage: /verification ' @@ -135,7 +135,7 @@ verification: code_expired: '&cVotre code d''identification a expiré !%nl%&cVeuillez re-exécuter une commande sensible pour recevoir un nouveau code.' email_needed: '&cAfin de vérifier votre identité, vous devez avoir un email lié à votre compte.%nl%&cPour cela, faites "/email add "' -# Time units +# Unités de temps time: second: 'seconde' seconds: 'secondes' @@ -146,7 +146,7 @@ time: day: 'jour' days: 'jours' -# Two-factor authentication +# Identification à deux facteurs two_factor: code_created: '&aVotre code secret est &2%code&a. Vous pouvez le scanner depuis &2%url' confirmation_required: 'Veuillez confirmer votre code secret en écrivant "/2fa confirm "' diff --git a/src/main/resources/messages/messages_pt.yml b/src/main/resources/messages/messages_pt.yml index 0f420833f4..2fd1332842 100644 --- a/src/main/resources/messages/messages_pt.yml +++ b/src/main/resources/messages/messages_pt.yml @@ -40,7 +40,7 @@ error: max_registration: '&cAtingiu o numero máximo de %reg_count contas registas, maximo de contas %max_acc' logged_in: '&cJá se encontra autenticado!' kick_for_vip: '&cUm jogador VIP entrou no servidor cheio!' - # TODO kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' + kick_unresolved_hostname: '&cOcorreu um erro: nome do servidor do jogador não resolvido!' tempban_max_logins: '&cVocê foi temporariamente banido por falhar muitas vezes o login.' # AntiBot diff --git a/src/main/resources/messages/messages_ru.yml b/src/main/resources/messages/messages_ru.yml index 644dd53acc..6d9b686021 100644 --- a/src/main/resources/messages/messages_ru.yml +++ b/src/main/resources/messages/messages_ru.yml @@ -1,17 +1,17 @@ # Registration registration: disabled: '&cРегистрация отключена.' - name_taken: '&cИгрок с таким именем уже зарегистрирован.' + name_taken: '&cИгрок с таким никнеймом уже зарегистрирован.' register_request: '&3Регистрация: /reg <пароль> <повтор пароля>' command_usage: '&cИспользование: /reg <пароль> <повтор пароля>' reg_only: '&4Вход только для зарегистрированных! Посетите http://сайт_сервера.ru для регистрации.' success: '&2Вы успешно зарегистрировались!' - kicked_admin_registered: 'Администратор зарегистрировал вас. Авторизируйтесь снова.' + kicked_admin_registered: 'Администратор зарегистрировал вас. Авторизуйтесь снова.' # Password errors on registration password: match_error: '&cПароли не совпадают.' - name_in_password: '&cНельзя использовать своё имя в качестве пароля.' + name_in_password: '&cНельзя использовать свой никнейм в качестве пароля.' unsafe_password: '&cТакой пароль небезопасен.' forbidden_characters: '&4Пароль содержит запрещённые символы. Разрешённые: %valid_chars' wrong_length: '&cПароль слишком длинный/короткий.' @@ -52,7 +52,7 @@ unregister: # Other messages misc: account_not_activated: '&cВаша уч. запись ещё не активирована. Проверьте электронную почту!' - password_changed: '&2Пароль изменён!' + password_changed: '&2Ваш пароль изменён!' logout: '&2Вы успешно вышли.' reload: '&6Конфигурация и база данных перезагружены.' usage_change_password: '&cИспользование: /changepassword <пароль> <новый пароль>' @@ -67,14 +67,14 @@ session: # Error messages when joining on_join_validation: same_ip_online: 'Игрок с данным IP-адресом уже играет на сервере!' - same_nick_online: '&4Игрок с данным именем уже играет на сервере!' - name_length: '&4Ваше имя слишком длинное/короткое.' - characters_in_name: '&4Пароль содержит запрещённые символы. Разрешённые: %valid_chars' + same_nick_online: '&4Игрок с данным никнеймом уже играет на сервере!' + name_length: '&4Ваш никнейм слишком длинный/короткий.' + characters_in_name: '&4Ваш никнейм содержит запрещённые символы. Разрешённые: %valid_chars' kick_full_server: '&4Сервер полон. Попробуйте зайти позже!' country_banned: '&4Вход с IP-адресов вашей страны запрещён на этом сервере.' - not_owner_error: 'Вы не являетесь владельцем данной уч. записи. Выберите себе другое имя!' - invalid_name_case: 'Неверное имя! Зайдите под именем %valid, а не %invalid.' - quick_command: 'Вы вводили команды слишком часто! Пожалуйста заходите снова и вводите команды помедленнее.' + not_owner_error: 'Вы не являетесь владельцем данной уч. записи. Выберите себе другой никнейм!' + invalid_name_case: 'Неверный никнейм! Зайдите под никнеймом %valid, а не %invalid.' + quick_command: 'Вы вводили команды слишком часто! Пожалуйста, переподключитесь и вводите команды медленнее.' # Email email: diff --git a/src/main/resources/messages/messages_tr.yml b/src/main/resources/messages/messages_tr.yml index 7d3d758284..8c86eebda0 100644 --- a/src/main/resources/messages/messages_tr.yml +++ b/src/main/resources/messages/messages_tr.yml @@ -40,7 +40,7 @@ error: max_registration: '&cSen maksimum kayit sinirini astin (%reg_count/%max_acc %reg_names)!' logged_in: '&cZaten giris yaptin!' kick_for_vip: '&3Bir VIP oyuna giris yaptigi icin atildin!' - # TODO kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!' + kick_unresolved_hostname: '&cBir hata olustu: cozumlenemeyen oyuncu bilgisayar adi!' tempban_max_logins: '&cBir cok kez yanlis giris yaptiginiz icin gecici olarak banlandiniz.' # AntiBot diff --git a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java index 4a8bf4b2f1..5fa11f6da0 100644 --- a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java +++ b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java @@ -90,8 +90,7 @@ public void initAuthMe() throws IOException { @Test public void shouldInitializeAllServices() { // given - PropertyReader reader = mock(PropertyReader.class, RETURNS_DEEP_STUBS); - given(reader.getList(anyString())).willReturn(Collections.emptyList()); + PropertyReader reader = mock(PropertyReader.class); PropertyResource resource = mock(PropertyResource.class); given(resource.createReader()).willReturn(reader); Settings settings = new Settings(dataFolder, resource, null, buildConfigurationData()); diff --git a/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java b/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java index daccc537a5..18ec07f70e 100644 --- a/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java +++ b/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java @@ -28,15 +28,16 @@ import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static fr.xephi.authme.IsEqualByReflectionMatcher.hasEqualValuesOnAllFields; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; @@ -512,6 +513,36 @@ public void shouldReturnGeoIpInfo() { assertThat(countryName, equalTo("Syldavia")); } + @Test + public void shouldReturnAuthMePlayerInfo() { + // given + PlayerAuth auth = PlayerAuth.builder() + .name("bobb") + .realName("Bobb") + .registrationDate(1433166082000L) + .build(); + given(dataSource.getAuth("bobb")).willReturn(auth); + + // when + Optional result = api.getPlayerInfo("bobb"); + + // then + AuthMePlayer playerInfo = result.get(); + assertThat(playerInfo.getName(), equalTo("Bobb")); + assertThat(playerInfo.getRegistrationDate(), equalTo(Instant.ofEpochMilli(1433166082000L))); + } + + @Test + public void shouldReturnNullForNonExistentAuth() { + // given / when + Optional result = api.getPlayerInfo("doesNotExist"); + + // then + assertThat(result.isPresent(), equalTo(false)); + verify(playerCache).getAuth("doesNotExist"); + verify(dataSource).getAuth("doesNotExist"); + } + private static Player mockPlayerWithName(String name) { Player player = mock(Player.class); given(player.getName()).willReturn(name); diff --git a/src/test/java/fr/xephi/authme/api/v3/AuthMePlayerImplTest.java b/src/test/java/fr/xephi/authme/api/v3/AuthMePlayerImplTest.java new file mode 100644 index 0000000000..aa8b50c953 --- /dev/null +++ b/src/test/java/fr/xephi/authme/api/v3/AuthMePlayerImplTest.java @@ -0,0 +1,95 @@ +package fr.xephi.authme.api.v3; + +import fr.xephi.authme.data.auth.PlayerAuth; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Test; + +import java.time.Instant; +import java.util.Optional; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +/** + * Test for {@link AuthMePlayerImpl}. + */ +public class AuthMePlayerImplTest { + + @Test + public void shouldMapNullWithoutError() { + // given / when / then + assertThat(AuthMePlayerImpl.fromPlayerAuth(null), emptyOptional()); + } + + @Test + public void shouldMapFromPlayerAuth() { + // given + PlayerAuth auth = PlayerAuth.builder() + .name("victor") + .realName("Victor") + .email("vic@example.com") + .registrationDate(1480075661000L) + .registrationIp("124.125.126.127") + .lastLogin(1542675632000L) + .lastIp("62.63.64.65") + .uuid(UUID.fromString("deadbeef-2417-4653-9026-feedbabeface")) + .build(); + + // when + Optional result = AuthMePlayerImpl.fromPlayerAuth(auth); + + // then + AuthMePlayer playerInfo = result.get(); + assertThat(playerInfo.getName(), equalTo("Victor")); + assertThat(playerInfo.getUuid().get(), equalTo(auth.getUuid())); + assertThat(playerInfo.getEmail().get(), equalTo(auth.getEmail())); + assertThat(playerInfo.getRegistrationDate(), equalTo(Instant.ofEpochMilli(auth.getRegistrationDate()))); + assertThat(playerInfo.getRegistrationIpAddress().get(), equalTo(auth.getRegistrationIp())); + assertThat(playerInfo.getLastLoginDate().get(), equalTo(Instant.ofEpochMilli(auth.getLastLogin()))); + assertThat(playerInfo.getLastLoginIpAddress().get(), equalTo(auth.getLastIp())); + } + + @Test + public void shouldHandleNullAndDefaultValues() { + // given + PlayerAuth auth = PlayerAuth.builder() + .name("victor") + .realName("Victor") + .email("your@email.com") // DB default + .registrationDate(1480075661000L) + .lastLogin(0L) // DB default + .lastIp("127.0.0.1") // DB default + .build(); + + // when + Optional result = AuthMePlayerImpl.fromPlayerAuth(auth); + + // then + AuthMePlayer playerInfo = result.get(); + assertThat(playerInfo.getName(), equalTo("Victor")); + assertThat(playerInfo.getUuid(), emptyOptional()); + assertThat(playerInfo.getEmail(), emptyOptional()); + assertThat(playerInfo.getRegistrationDate(), equalTo(Instant.ofEpochMilli(auth.getRegistrationDate()))); + assertThat(playerInfo.getRegistrationIpAddress(), emptyOptional()); + assertThat(playerInfo.getLastLoginDate(), emptyOptional()); + assertThat(playerInfo.getLastLoginIpAddress(), emptyOptional()); + } + + private static Matcher> emptyOptional() { + return new TypeSafeMatcher>() { + + @Override + public void describeTo(Description description) { + description.appendText("an empty optional"); + } + + @Override + protected boolean matchesSafely(Optional item) { + return !item.isPresent(); + } + }; + } +} diff --git a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java index 295bcacb7b..3667e1bea1 100644 --- a/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java +++ b/src/test/java/fr/xephi/authme/listener/OnJoinVerifierTest.java @@ -439,18 +439,18 @@ public void shouldKickUserForFailedAntibotCheck() { */ @Test public void shouldNotCheckCountry() throws FailedVerificationException { + // given String name = "david"; String ip = "127.0.0.1"; - // protection setting disabled given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(false); given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(true); - onJoinVerifier.checkPlayerCountry(name, ip, false); - verifyNoInteractions(validationService); - // protection for registered players disabled - given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(false); + // when + onJoinVerifier.checkPlayerCountry(name, ip, false); onJoinVerifier.checkPlayerCountry(name, ip, true); + + // then verifyNoInteractions(validationService); } diff --git a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java index 04f45ab1c0..5f89865183 100644 --- a/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java +++ b/src/test/java/fr/xephi/authme/listener/PlayerListenerTest.java @@ -935,7 +935,6 @@ public void shouldAllowInventoryOpen() { // given HumanEntity player = mock(Player.class); InventoryView transaction = mock(InventoryView.class); - given(transaction.getPlayer()).willReturn(player); InventoryOpenEvent event = new InventoryOpenEvent(transaction); given(event.getPlayer()).willReturn(player); given(listenerService.shouldCancelEvent(player)).willReturn(false); @@ -953,8 +952,8 @@ public void shouldCancelInventoryOpen() { // given HumanEntity player = mock(Player.class); InventoryView transaction = mock(InventoryView.class); + given(transaction.getTitle()).willReturn("Spawn"); given(settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES)).willReturn(Collections.emptySet()); - given(transaction.getPlayer()).willReturn(player); InventoryOpenEvent event = new InventoryOpenEvent(transaction); given(event.getPlayer()).willReturn(player); given(listenerService.shouldCancelEvent(player)).willReturn(true); diff --git a/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java b/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java index 0e7d9c37f4..8df9940849 100644 --- a/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java +++ b/src/test/java/fr/xephi/authme/security/totp/TotpAuthenticatorTest.java @@ -60,8 +60,8 @@ public void shouldGenerateTotpKey() { TotpGenerationResult key2 = totpAuthenticator.generateTotpKey(player); // then - assertThat(key1.getTotpKey(), stringWithLength(16)); - assertThat(key2.getTotpKey(), stringWithLength(16)); + assertThat(key1.getTotpKey(), stringWithLength(32)); + assertThat(key2.getTotpKey(), stringWithLength(32)); assertThat(key1.getAuthenticatorQrCodeUrl(), startsWith("https://api.qrserver.com/v1/create-qr-code/?data=")); assertThat(key1.getAuthenticatorQrCodeUrl(), containsString("MCtopia")); assertThat(key2.getAuthenticatorQrCodeUrl(), startsWith("https://api.qrserver.com/v1/create-qr-code/?data="));