From 88629702f508ed2c97d81aae575c95d89cb7edfe Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 9 Jan 2016 09:30:49 +0100 Subject: [PATCH] #347 Test that all read properties exist as Property field - Create consistency test to verify that all properties in config.yml are defined as a Property field in a SettingsClass implementation (currently fails) - Add some missing properties - Minor: convert tabs to spaces --- .../settings/custom/ConverterSettings.java | 12 +- .../settings/custom/DatabaseSettings.java | 54 +++---- .../authme/settings/custom/EmailSettings.java | 34 ++-- .../authme/settings/custom/HooksSettings.java | 12 +- .../settings/custom/PluginSettings.java | 46 ++++++ .../settings/custom/ProtectionSettings.java | 16 +- .../authme/settings/custom/PurgeSettings.java | 18 +-- .../settings/custom/RestrictionSettings.java | 147 ++++++++++++++++++ .../settings/custom/SecuritySettings.java | 16 +- .../custom/SettingsFieldRetriever.java | 5 +- .../settings/propertymap/PropertyMap.java | 19 ++- src/main/resources/config.yml | 2 - .../custom/ConfigFileConsistencyTest.java | 57 ++++++- .../custom/SettingsClassConsistencyTest.java | 2 +- 14 files changed, 345 insertions(+), 95 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java create mode 100644 src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java diff --git a/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java b/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java index f208727b7..f32cf7483 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java @@ -10,19 +10,19 @@ import static fr.xephi.authme.settings.domain.PropertyType.STRING; public class ConverterSettings implements SettingsClass { - @Comment("Rakamak file name") - public static final Property RAKAMAK_FILE_NAME = + @Comment("Rakamak file name") + public static final Property RAKAMAK_FILE_NAME = newProperty(STRING, "Converter.Rakamak.fileName", "users.rak"); - @Comment("Rakamak use IP?") - public static final Property RAKAMAK_USE_IP = + @Comment("Rakamak use IP?") + public static final Property RAKAMAK_USE_IP = newProperty(BOOLEAN, "Converter.Rakamak.useIP", false); - @Comment("Rakamak IP file name") + @Comment("Rakamak IP file name") public static final Property RAKAMAK_IP_FILE_NAME = newProperty(STRING, "Converter.Rakamak.ipFileName", "UsersIp.rak"); - @Comment("CrazyLogin database file name") + @Comment("CrazyLogin database file name") public static final Property CRAZYLOGIN_FILE_NAME = newProperty(STRING, "Converter.CrazyLogin.fileName", "accounts.db"); diff --git a/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java b/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java index d638fd8f0..582e5d6eb 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java @@ -11,100 +11,100 @@ import static fr.xephi.authme.settings.domain.PropertyType.STRING; public class DatabaseSettings implements SettingsClass { - @Comment({"What type of database do you want to use?", - "Valid values: sqlite, mysql"}) + @Comment({"What type of database do you want to use?", + "Valid values: sqlite, mysql"}) public static final Property BACKEND = newProperty(DataSource.DataSourceType.class, "DataSource.backend", DataSource.DataSourceType.SQLITE); - @Comment("Enable database caching, should improve database performance") + @Comment("Enable database caching, should improve database performance") public static final Property USE_CACHING = newProperty(BOOLEAN, "DataSource.caching", true); - @Comment("Database host address") + @Comment("Database host address") public static final Property MYSQL_HOST = newProperty(STRING, "DataSource.mySQLHost", "127.0.0.1"); - @Comment("Database port") + @Comment("Database port") public static final Property MYSQL_PORT = newProperty(STRING, "DataSource.mySQLPort", "3306"); - @Comment("Username about Database Connection Infos") + @Comment("Username about Database Connection Infos") public static final Property MYSQL_USERNAME = newProperty(STRING, "DataSource.mySQLUsername", "authme"); - @Comment("Password about Database Connection Infos") + @Comment("Password about Database Connection Infos") public static final Property MYSQL_PASSWORD = newProperty(STRING, "DataSource.mySQLPassword", "123456"); - @Comment("Database Name, use with converters or as SQLITE database name") + @Comment("Database Name, use with converters or as SQLITE database name") public static final Property MYSQL_DATABASE = newProperty(STRING, "DataSource.mySQLDatabase", "authme"); - @Comment("Table of the database") + @Comment("Table of the database") public static final Property MYSQL_TABLE = newProperty(STRING, "DataSource.mySQLTablename", "authme"); - @Comment("Column of IDs to sort data") + @Comment("Column of IDs to sort data") public static final Property MYSQL_COL_ID = newProperty(STRING, "DataSource.mySQLColumnId", "id"); - @Comment("Column for storing or checking players nickname") + @Comment("Column for storing or checking players nickname") public static final Property MYSQL_COL_NAME = newProperty(STRING, "DataSource.mySQLColumnName", "username"); - @Comment("Column for storing or checking players RealName ") + @Comment("Column for storing or checking players RealName ") public static final Property MYSQL_COL_REALNAME = newProperty(STRING, "DataSource.mySQLRealName", "realname"); - @Comment("Column for storing players passwords") + @Comment("Column for storing players passwords") public static final Property MYSQL_COL_PASSWORD = newProperty(STRING, "DataSource.mySQLColumnPassword", "password"); - @Comment("Column for storing players passwords salts") + @Comment("Column for storing players passwords salts") public static final Property MYSQL_COL_SALT = newProperty(STRING, "ExternalBoardOptions.mySQLColumnSalt", ""); - @Comment("Column for storing players emails") + @Comment("Column for storing players emails") public static final Property MYSQL_COL_EMAIL = newProperty(STRING, "DataSource.mySQLColumnEmail", "email"); - @Comment("Column for storing if a player is logged in or not") + @Comment("Column for storing if a player is logged in or not") public static final Property MYSQL_COL_ISLOGGED = newProperty(STRING, "DataSource.mySQLColumnLogged", "isLogged"); - @Comment("Column for storing players ips") + @Comment("Column for storing players ips") public static final Property MYSQL_COL_IP = newProperty(STRING, "DataSource.mySQLColumnIp", "ip"); - @Comment("Column for storing players lastlogins") + @Comment("Column for storing players lastlogins") public static final Property MYSQL_COL_LASTLOGIN = newProperty(STRING, "DataSource.mySQLColumnLastLogin", "lastlogin"); - @Comment("Column for storing player LastLocation - X") + @Comment("Column for storing player LastLocation - X") public static final Property MYSQL_COL_LASTLOC_X = newProperty(STRING, "DataSource.mySQLlastlocX", "x"); - @Comment("Column for storing player LastLocation - Y") + @Comment("Column for storing player LastLocation - Y") public static final Property MYSQL_COL_LASTLOC_Y = newProperty(STRING, "DataSource.mySQLlastlocY", "y"); - @Comment("Column for storing player LastLocation - Z") + @Comment("Column for storing player LastLocation - Z") public static final Property MYSQL_COL_LASTLOC_Z = newProperty(STRING, "DataSource.mySQLlastlocZ", "z"); - @Comment("Column for storing player LastLocation - World Name") + @Comment("Column for storing player LastLocation - World Name") public static final Property MYSQL_COL_LASTLOC_WORLD = newProperty(STRING, "DataSource.mySQLlastlocWorld", "world"); - @Comment("Column for storing players groups") + @Comment("Column for storing players groups") public static final Property MYSQL_COL_GROUP = newProperty(STRING, "ExternalBoardOptions.mySQLColumnGroup", ""); - @Comment("Enable this when you allow registration through a website") - public static final Property MYSQL_WEBSITE = + @Comment("Enable this when you allow registration through a website") + public static final Property MYSQL_WEBSITE = newProperty(BOOLEAN, "DataSource.mySQLWebsite", false); - private DatabaseSettings() { - } + private DatabaseSettings() { + } } diff --git a/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java b/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java index dcde50191..683143652 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java @@ -14,51 +14,55 @@ import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST; public class EmailSettings implements SettingsClass { - @Comment("Email SMTP server host") - public static final Property SMTP_HOST = + @Comment("Email SMTP server host") + public static final Property SMTP_HOST = newProperty(STRING, "Email.mailSMTP", "smtp.gmail.com"); - @Comment("Email SMTP server port") + @Comment("Email SMTP server port") public static final Property SMTP_PORT = newProperty(INTEGER, "Email.mailPort", 465); - @Comment("Email account which sends the mails") + @Comment("Email account which sends the mails") public static final Property MAIL_ACCOUNT = newProperty(STRING, "Email.mailAccount", ""); - @Comment("Email account password") + @Comment("Email account password") public static final Property MAIL_PASSWORD = newProperty(STRING, "Email.mailPassword", ""); - @Comment("Recovery password length") + @Comment("Custom sender name, replacing the mailAccount name in the email") + public static final Property MAIL_SENDER_NAME = + newProperty("Email.mailSenderName", ""); + + @Comment("Recovery password length") public static final Property RECOVERY_PASSWORD_LENGTH = newProperty(INTEGER, "Email.RecoveryPasswordLength", 8); - @Comment("Mail Subject") + @Comment("Mail Subject") public static final Property RECOVERY_MAIL_SUBJECT = newProperty(STRING, "Email.mailSubject", "Your new AuthMe password"); - @Comment("Like maxRegPerIP but with email") + @Comment("Like maxRegPerIP but with email") public static final Property MAX_REG_PER_EMAIL = newProperty(INTEGER, "Email.maxRegPerEmail", 1); - @Comment("Recall players to add an email?") + @Comment("Recall players to add an email?") public static final Property RECALL_PLAYERS = newProperty(BOOLEAN, "Email.recallPlayers", false); - @Comment("Delay in minute for the recall scheduler") + @Comment("Delay in minute for the recall scheduler") public static final Property DELAY_RECALL = newProperty(INTEGER, "Email.delayRecall", 5); - @Comment("Blacklist these domains for emails") - public static final Property> DOMAIN_BLACKLIST = + @Comment("Blacklist these domains for emails") + public static final Property> DOMAIN_BLACKLIST = newProperty(STRING_LIST, "Email.emailBlacklisted", "10minutemail.com"); - @Comment("Whitelist ONLY these domains for emails") - public static final Property> DOMAIN_WHITELIST = + @Comment("Whitelist ONLY these domains for emails") + public static final Property> DOMAIN_WHITELIST = newProperty(STRING_LIST, "Email.emailWhitelisted"); - @Comment("Send the new password drawn in an image?") + @Comment("Send the new password drawn in an image?") public static final Property PASSWORD_AS_IMAGE = newProperty(BOOLEAN, "Email.generateImage", false); diff --git a/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java b/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java index 707821e05..d838c33ad 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java @@ -9,27 +9,27 @@ import static fr.xephi.authme.settings.domain.Property.newProperty; public class HooksSettings implements SettingsClass { - @Comment("Do we need to hook with multiverse for spawn checking?") + @Comment("Do we need to hook with multiverse for spawn checking?") public static final Property MULTIVERSE = newProperty(PropertyType.BOOLEAN, "Hooks.multiverse", true); - @Comment("Do we need to hook with BungeeCord?") + @Comment("Do we need to hook with BungeeCord?") public static final Property BUNGEECORD = newProperty(PropertyType.BOOLEAN, "Hooks.bungeecord", false); - @Comment("Send player to this BungeeCord server after register/login") + @Comment("Send player to this BungeeCord server after register/login") public static final Property BUNGEECORD_SERVER = newProperty(PropertyType.STRING, "Hooks.sendPlayerTo", ""); - @Comment("Do we need to disable Essentials SocialSpy on join?") + @Comment("Do we need to disable Essentials SocialSpy on join?") public static final Property DISABLE_SOCIAL_SPY = newProperty(PropertyType.BOOLEAN, "Hooks.disableSocialSpy", false); - @Comment("Do we need to force /motd Essentials command on join?") + @Comment("Do we need to force /motd Essentials command on join?") public static final Property USE_ESSENTIALS_MOTD = newProperty(PropertyType.BOOLEAN, "Hooks.useEssentialsMotd", false); - @Comment("Do we need to cache custom Attributes?") + @Comment("Do we need to cache custom Attributes?") public static final Property CACHE_CUSTOM_ATTRIBUTES = newProperty(PropertyType.BOOLEAN, "Hooks.customAttributes", false); diff --git a/src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java b/src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java new file mode 100644 index 000000000..9778d04e4 --- /dev/null +++ b/src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java @@ -0,0 +1,46 @@ +package fr.xephi.authme.settings.custom; + +import fr.xephi.authme.settings.domain.Comment; +import fr.xephi.authme.settings.domain.Property; +import fr.xephi.authme.settings.domain.SettingsClass; + +import static fr.xephi.authme.settings.domain.Property.newProperty; + +public class PluginSettings implements SettingsClass { + + @Comment("The name shown in the help messages") + public static final Property HELP_HEADER = + newProperty("settings.helpHeader", "AuthMeReloaded"); + + @Comment({ + "Do you want to enable the session feature?", + "If enabled, when a player authenticates successfully,", + "his IP and his nickname is saved.", + "The next time the player joins the server, if his IP", + "is the same as last time and the timeout hasn't", + "expired, he will not need to authenticate." + }) + public static final Property SESSIONS_ENABLED = + newProperty("settings.sessions.enabled", false); + + @Comment({ + "After how many minutes should a session expire?", + "0 for unlimited time (Very dangerous, use it at your own risk!)", + "Remember that sessions will end only after the timeout, and", + "if the player's IP has changed but the timeout hasn't expired,", + "the player will be kicked from the server due to invalid session" + }) + public static final Property SESSIONS_TIMEOUT = + newProperty("settings.sessions.timeout", 10); + + @Comment({ + "Should the session expire if the player tries to log in with", + "another IP address?" + }) + public static final Property SESSIONS_EXPIRE_ON_IP_CHANGE = + newProperty("settings.sessions.sessionExpireOnIpChange", true); + + private PluginSettings() { + } + +} diff --git a/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java b/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java index b71a9589b..2582c277f 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java @@ -14,29 +14,29 @@ import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST; public class ProtectionSettings implements SettingsClass { - @Comment("Enable some servers protection (country based login, antibot)") + @Comment("Enable some servers protection (country based login, antibot)") public static final Property ENABLE_PROTECTION = newProperty(BOOLEAN, "Protection.enableProtection", false); - @Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes", - "PLEASE USE QUOTES!"}) + @Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes", + "PLEASE USE QUOTES!"}) public static final Property> COUNTRIES_WHITELIST = newProperty(STRING_LIST, "Protection.countries", "US", "GB", "A1"); - @Comment({"Countries not allowed to join the server and register", - "PLEASE USE QUOTES!"}) + @Comment({"Countries not allowed to join the server and register", + "PLEASE USE QUOTES!"}) public static final Property> COUNTRIES_BLACKLIST = newProperty(STRING_LIST, "Protection.countriesBlacklist"); - @Comment("Do we need to enable automatic antibot system?") + @Comment("Do we need to enable automatic antibot system?") public static final Property ENABLE_ANTIBOT = newProperty(BOOLEAN, "Protection.enableAntiBot", false); - @Comment("Max number of player allowed to login in 5 secs before enable AntiBot system automatically") + @Comment("Max number of player allowed to login in 5 secs before enable AntiBot system automatically") public static final Property ANTIBOT_SENSIBILITY = newProperty(INTEGER, "Protection.antiBotSensibility", 5); - @Comment("Duration in minutes of the antibot automatic system") + @Comment("Duration in minutes of the antibot automatic system") public static final Property ANTIBOT_DURATION = newProperty(INTEGER, "Protection.antiBotDuration", 10); diff --git a/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java b/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java index cff4a7c98..5fcc139d7 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java @@ -11,35 +11,35 @@ import static fr.xephi.authme.settings.domain.PropertyType.STRING; public class PurgeSettings implements SettingsClass { - @Comment("If enabled, AuthMe automatically purges old, unused accounts") - public static final Property USE_AUTO_PURGE = + @Comment("If enabled, AuthMe automatically purges old, unused accounts") + public static final Property USE_AUTO_PURGE = newProperty(BOOLEAN, "Purge.useAutoPurge", false); - @Comment("Number of Days an account become Unused") + @Comment("Number of Days an account become Unused") public static final Property DAYS_BEFORE_REMOVE_PLAYER = newProperty(INTEGER, "Purge.daysBeforeRemovePlayer", 60); - @Comment("Do we need to remove the player.dat file during purge process?") + @Comment("Do we need to remove the player.dat file during purge process?") public static final Property REMOVE_PLAYER_DAT = newProperty(BOOLEAN, "Purge.removePlayerDat", false); - @Comment("Do we need to remove the Essentials/users/player.yml file during purge process?") + @Comment("Do we need to remove the Essentials/users/player.yml file during purge process?") public static final Property REMOVE_ESSENTIALS_FILES = newProperty(BOOLEAN, "Purge.removeEssentialsFile", false); - @Comment("World where are players.dat stores") + @Comment("World where are players.dat stores") public static final Property DEFAULT_WORLD = newProperty(STRING, "Purge.defaultWorld", "world"); - @Comment("Do we need to remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge process ?") + @Comment("Do we need to remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge process ?") public static final Property REMOVE_LIMITED_CREATIVE_INVENTORIES = newProperty(BOOLEAN, "Purge.removeLimitedCreativesInventories", false); - @Comment("Do we need to remove the AntiXRayData/PlayerData/player file during purge process?") + @Comment("Do we need to remove the AntiXRayData/PlayerData/player file during purge process?") public static final Property REMOVE_ANTI_XRAY_FILE = newProperty(BOOLEAN, "Purge.removeAntiXRayFile", false); - @Comment("Do we need to remove permissions?") + @Comment("Do we need to remove permissions?") public static final Property REMOVE_PERMISSIONS = newProperty(BOOLEAN, "Purge.removePermissions", false); diff --git a/src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java b/src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java new file mode 100644 index 000000000..f5fa9c061 --- /dev/null +++ b/src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java @@ -0,0 +1,147 @@ +package fr.xephi.authme.settings.custom; + +import fr.xephi.authme.settings.domain.Comment; +import fr.xephi.authme.settings.domain.Property; +import fr.xephi.authme.settings.domain.PropertyType; +import fr.xephi.authme.settings.domain.SettingsClass; + +import java.util.List; + +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?", + "Keep in mind that this feature also blocks all commands not", + "listed in the list below."}) + public static final Property ALLOW_CHAT = + newProperty("settings.restrictions.allowChat", false); + + @Comment("Allowed commands for unauthenticated players") + public static final Property> ALLOW_COMMANDS = + newProperty(PropertyType.STRING_LIST, "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 ot the comment + public static final Property MAX_REGISTRATION_PER_IP = + newProperty("settings.restrictions.maxRegPerIp", 1); + + @Comment("Minimum allowed username length") + public static final Property MIN_NICKNAME_LENGTH = + newProperty("settings.restrictions.minNicknameLength", 4); + + @Comment("Maximum allowed username length") + public static final Property MAX_NICKNAME_LENGTH = + newProperty("settings.restrictions.maxNicknameLength", 16); + + @Comment({ + "When this setting is enabled, online players can't be kicked out", + "due to \"Logged in from another Location\"", + "This setting will prevent potential security exploits."}) + public static final Property FORCE_SINGLE_SESSION = + newProperty("settings.restrictions.ForceSingleSession", true); + + @Comment({ + "If enabled, every player will be teleported to the world spawnpoint", + "after successful authentication.", + "The quit location of the player will be overwritten.", + "This is different from \"teleportUnAuthedToSpawn\" that teleport player", + "back to his quit location after the authentication."}) + public static final Property FORCE_SPAWN_LOCATION_AFTER_LOGIN = + newProperty("settings.restrictions.ForceSpawnLocOnJoinEnabled", false); + + @Comment("This option will save the quit location of the players.") + public static final Property SAVE_QUIT_LOCATION = + newProperty("settings.restrictions.SaveQuitLocation", false); + + @Comment({ + "To activate the restricted user feature you need", + "to enable this option and configure the AllowedRestrctedUser field."}) + public static final Property ENABLE_RESTRICTED_USERS = + newProperty("settings.restrictions.AllowRestrictedUser", false); + + @Comment({ + "The restricted user feature will kick players listed below", + "if they don't match the defined IP address.", + "Example:", + " AllowedRestrictedUser:", + " - playername;127.0.0.1"}) + public static final Property> ALLOWED_RESTRICTED_USERS = + newProperty(PropertyType.STRING_LIST, "settings.restrictions.AllowedRestrictedUser"); + + @Comment("Should unregistered players be kicked immediately?") + public static final Property KICK_NON_REGISTERED = + newProperty("settings.restrictions.kickNonRegistered", false); + + @Comment("Should players be kicked on wrong password?") + public static final Property KICK_ON_WRONG_PASSWORD = + newProperty("settings.restrictions.kickOnWrongPassword", false); + + @Comment({ + "Should not logged in players be teleported to the spawn?", + "After the authentication they will be teleported back to", + "their normal position."}) + public static final Property TELEPORT_UNAUTHED_TO_SPAWN = + newProperty("settings.restrictions.teleportUnAuthedToSpawn", false); + + @Comment("Can unregistered players walk around?") + public static final Property ALLOW_UNAUTHED_MOVEMENT = + newProperty("settings.restrictions.allowMovement", false); + + @Comment({ + "Should not authenticated players have speed = 0?", + "This will reset the fly/walk speed to default value after the login."}) + public static final Property REMOVE_SPEED = + newProperty("settings.restrictions.removeSpeed", true); + + @Comment({ + "After how many seconds should players who fail to login or register", + "be kicked? Set to 0 to disable."}) + public static final Property TIMEOUT = + newProperty("settings.restrictions.timeout", 30); + + @Comment("Regex syntax of allowed characters in the player name.") + public static final Property ALLOWED_NICKNAME_CHARACTERS = + newProperty("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_]*"); + + @Comment({ + "How far can unregistered players walk?", + "Set to 0 for unlimited radius" + }) + public static final Property ALLOWED_MOVEMENT_RADIUS = + newProperty("settings.restrictions.allowedMovementRadius", 100); + + @Comment({ + "Enable double check of password when you register", + "when it's true, registration requires that kind of command:", + "/register "}) + public static final Property ENABLE_PASSWORD_CONFIRMATION = + newProperty("settings.restrictions.enablePasswordConfirmation", true); + + @Comment("Should we protect the player inventory before logging in?") + public static final Property PROTECT_INVENTORY_BEFORE_LOGIN = + newProperty("settings.restrictions.ProtectInventoryBeforeLogIn", true); + + @Comment({ + "Should we display all other accounts from a player when he joins?", + "permission: /authme.admin.accounts"}) + public static final Property DISPLAY_OTHER_ACCOUNTS = + newProperty("settings.restrictions.displayOtherAccounts", true); + + @Comment({ + "WorldNames where we need to force the spawn location for ForceSpawnLocOnJoinEnabled", + "Case-sensitive!"}) + public static final Property> FORCE_SPAWN_ON_WORLDS = + newProperty(PropertyType.STRING_LIST, "settings.restrictions.ForceSpawnOnTheseWorlds", + "world", "world_nether", "world_the_end"); + + @Comment("Ban ip when the ip is not the ip registered in database") + public static final Property BAN_UNKNOWN_IP = + newProperty("settings.restrictions.banUnsafedIP", false); + + private RestrictionSettings() { + } + +} diff --git a/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java b/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java index c18e7e7ca..1605c166f 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java +++ b/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java @@ -10,33 +10,33 @@ import static fr.xephi.authme.settings.domain.PropertyType.INTEGER; public class SecuritySettings implements SettingsClass { - @Comment({"Stop the server if we can't contact the sql database", + @Comment({"Stop the server if we can't contact the sql database", "Take care with this, if you set this to false,", "AuthMe will automatically disable and the server won't be protected!"}) - public static final Property STOP_SERVER_ON_PROBLEM = + public static final Property STOP_SERVER_ON_PROBLEM = newProperty(BOOLEAN, "Security.SQLProblem.stopServer", true); - @Comment("/reload support") + @Comment("/reload support") public static final Property USE_RELOAD_COMMAND_SUPPORT = newProperty(BOOLEAN, "Security.ReloadCommand.useReloadCommandSupport", true); - @Comment("Remove spam from console?") + @Comment("Remove spam from console?") public static final Property REMOVE_SPAM_FROM_CONSOLE = newProperty(BOOLEAN, "Security.console.noConsoleSpam", false); - @Comment("Remove passwords from console?") + @Comment("Remove passwords from console?") public static final Property REMOVE_PASSWORD_FROM_CONSOLE = newProperty(BOOLEAN, "Security.console.removePassword", true); - @Comment("Player need to put a captcha when he fails too lot the password") + @Comment("Player need to put a captcha when he fails too lot the password") public static final Property USE_CAPTCHA = newProperty(BOOLEAN, "Security.captcha.useCaptcha", false); - @Comment("Max allowed tries before request a captcha") + @Comment("Max allowed tries before request a captcha") public static final Property MAX_LOGIN_TRIES_BEFORE_CAPTCHA = newProperty(INTEGER, "Security.captcha.maxLoginTry", 5); - @Comment("Captcha length") + @Comment("Captcha length") public static final Property CAPTCHA_LENGTH = newProperty(INTEGER, "Security.captcha.captchaLength", 5); diff --git a/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java b/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java index 9727ffac7..f5c7f23d8 100644 --- a/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java +++ b/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java @@ -18,8 +18,9 @@ final class SettingsFieldRetriever { /** The classes to scan for properties. */ private static final List> CONFIGURATION_CLASSES = Arrays.asList( - ConverterSettings.class, DatabaseSettings.class, EmailSettings.class, HooksSettings.class, - ProtectionSettings.class, PurgeSettings.class, SecuritySettings.class); + ConverterSettings.class, PluginSettings.class, RestrictionSettings.class, + DatabaseSettings.class, EmailSettings.class, HooksSettings.class, + ProtectionSettings.class, PurgeSettings.class, SecuritySettings.class); private SettingsFieldRetriever() { } diff --git a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java index 07cfc7144..9cac52d30 100644 --- a/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java +++ b/src/main/java/fr/xephi/authme/settings/propertymap/PropertyMap.java @@ -14,7 +14,7 @@ import java.util.TreeMap; */ public class PropertyMap { - private Map, String[]> propertyMap; + private Map, String[]> map; private PropertyMapComparator comparator; /** @@ -22,7 +22,7 @@ public class PropertyMap { */ public PropertyMap() { comparator = new PropertyMapComparator(); - propertyMap = new TreeMap<>(comparator); + map = new TreeMap<>(comparator); } /** @@ -33,7 +33,7 @@ public class PropertyMap { */ public void put(Property property, String[] comments) { comparator.add(property); - propertyMap.put(property, comments); + map.put(property, comments); } /** @@ -42,7 +42,7 @@ public class PropertyMap { * @return The entry set */ public Set, String[]>> entrySet() { - return propertyMap.entrySet(); + return map.entrySet(); } /** @@ -51,7 +51,16 @@ public class PropertyMap { * @return The key set */ public Set> keySet() { - return propertyMap.keySet(); + return map.keySet(); + } + + /** + * Return the size of the map. + * + * @return The size + */ + public int size() { + return map.size(); } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bc1725133..960cfc6ee 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -340,8 +340,6 @@ Email: RecoveryPasswordLength: 8 # Email subject of password get mailSubject: 'Your new AuthMe Password' - # Email text here - mailText: 'Dear ,

This is your new AuthMe password for the server

:



Do not forget to change password after login!
/changepassword newPassword' # Like maxRegPerIp but with email maxRegPerEmail: 1 # Recall players to add an email? diff --git a/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java index b5bdc4df9..eb12ab030 100644 --- a/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java @@ -1,14 +1,24 @@ package fr.xephi.authme.settings.custom; +import fr.xephi.authme.settings.domain.Property; +import fr.xephi.authme.settings.propertymap.PropertyMap; +import fr.xephi.authme.util.StringUtils; +import org.bukkit.configuration.MemorySection; +import org.bukkit.configuration.file.YamlConfiguration; import org.junit.Test; import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; -import static org.junit.Assume.assumeThat; +import static org.junit.Assert.fail; /** * Test for {@link NewSetting} and the project's config.yml, @@ -16,14 +26,15 @@ import static org.junit.Assume.assumeThat; */ public class ConfigFileConsistencyTest { + /** The file name of the project's sample config file. */ + private static final String CONFIG_FILE = "/config.yml"; + @Test public void shouldHaveAllConfigs() throws IOException { - URL url = this.getClass().getResource("/config.yml"); - File configFile = new File(url.getFile()); - // given - assumeThat(configFile.exists(), equalTo(true)); - NewSetting settings = new NewSetting(configFile); + URL url = this.getClass().getResource(CONFIG_FILE); + File configFile = new File(url.getFile()); + NewSetting settings = new NewSetting(YamlConfiguration.loadConfiguration(configFile), new File("bogus"), null); // when boolean result = settings.containsAllSettings(SettingsFieldRetriever.getAllPropertyFields()); @@ -32,4 +43,38 @@ public class ConfigFileConsistencyTest { assertThat(result, equalTo(true)); } + @Test + public void shouldNotHaveUnknownConfigs() { + // given + URL url = this.getClass().getResource(CONFIG_FILE); + File configFile = new File(url.getFile()); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); + Map allReadProperties = configuration.getValues(true); + Set knownKeys = getAllKnownPropertyPaths(); + + // when + List unknownPaths = new ArrayList<>(); + for (Map.Entry entry : allReadProperties.entrySet()) { + // The value being a MemorySection means it's a parent node + if (!(entry.getValue() instanceof MemorySection) && !knownKeys.contains(entry.getKey())) { + unknownPaths.add(entry.getKey()); + } + } + + // then + if (!unknownPaths.isEmpty()) { + fail("Found " + unknownPaths.size() + " unknown property paths in the project's config.yml: \n- " + + StringUtils.join("\n- ", unknownPaths)); + } + } + + private static Set getAllKnownPropertyPaths() { + PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields(); + Set paths = new HashSet<>(propertyMap.size()); + for (Property property : propertyMap.keySet()) { + paths.add(property.getPath()); + } + return paths; + } + } diff --git a/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java index c06ed11b1..6dab6bdfc 100644 --- a/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java @@ -54,7 +54,7 @@ public class SettingsClassConsistencyTest { for (Field field : fields) { if (Property.class.isAssignableFrom(field.getType())) { String fieldName = "Field " + clazz.getSimpleName() + "#" + field.getName(); - assertThat(fieldName + "should be public, static, and final", + assertThat(fieldName + " should be public, static, and final", isValidConstantField(field), equalTo(true)); } }