Merge remote-tracking branch 'refs/remotes/AuthMe/master'

This commit is contained in:
Martin 2017-03-06 06:16:34 +02:00
commit 7f8b31f9d4
38 changed files with 324 additions and 91 deletions

164
.checkstyle.xml Normal file
View File

@ -0,0 +1,164 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
<module name="SuppressWarningsHolder"/>
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="TodoComment">
<property name="format" value="TODO|FIXME"/>
</module>
<module name="GenericWhitespace"/>
<module name="AvoidStarImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<module name="OneTopLevelClass"/>
<module name="FinalClass"/>
<module name="HideUtilityClassConstructor"/>
<module name="InnerTypeLast"/>
<module name="VisibilityModifier"/>
<module name="AvoidNestedBlocks"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="RightCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<property name="allowOneCharVarInForLoop" value="true"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="MethodParamPad"/>
<module name="BooleanExpressionComplexity">
<property name="max" value="5"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
</module>
<module name="CyclomaticComplexity">
<property name="max" value="15"/>
</module>
<module name="JavaNCSS">
<property name="methodMaximum" value="40"/>
<property name="classMaximum" value="1000"/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="package"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="minLineCount" value="4"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoredTags" value="@return"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="ignore|ignored"/>
</module>
</module>
<module name="FileTabCharacter"/>
</module>

30
.codeclimate.yml Normal file
View File

@ -0,0 +1,30 @@
engines:
duplication:
enabled: true
config:
languages:
- java
- php
checkstyle:
enabled: true
channel: beta
config: '.checkstyle.xml'
pmd:
enabled: true
channel: beta
checks:
AvoidUsingHardCodedIP:
enabled: false
ratings:
paths:
# Check only production files
- 'src/main/java/**'
exclude_paths:
# Exclude code from third-party sources
- 'src/main/java/fr/xephi/authme/mail/OAuth2Provider.java'
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java'
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClientFactory.java'
- 'src/main/java/fr/xephi/authme/security/crypts/BCryptService.java'
- 'src/main/java/fr/xephi/authme/security/crypts/PHPBB.java'
- 'src/main/java/fr/xephi/authme/security/crypts/WHIRLPOOL.java'
- 'src/main/java/fr/xephi/authme/security/crypts/WORDPRESS.java'

View File

@ -19,20 +19,14 @@
- Project status: - Project status:
- Dependencies: [![Dependencies status](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d/badge.svg)](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d) - Dependencies: [![Dependencies status](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d/badge.svg)](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d)
- Test coverage: [![Coverage status](https://coveralls.io/repos/AuthMe-Team/AuthMeReloaded/badge.svg?branch=master&service=github)](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master) - Test coverage: [![Coverage status](https://coveralls.io/repos/AuthMe-Team/AuthMeReloaded/badge.svg?branch=master&service=github)](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master)
- Code climate: [![Code Climate](https://codeclimate.com/github/AuthMe/AuthMeReloaded/badges/gpa.svg)](https://codeclimate.com/github/AuthMe/AuthMeReloaded)
- Development resources: - Development resources:
- <a href="http://ci.xephi.fr/job/AuthMeReloaded/javadoc/">JavaDocs</a> - <a href="http://ci.xephi.fr/job/AuthMeReloaded/javadoc/">JavaDocs</a>
- <a href="http://ci.xephi.fr/plugin/repository/everything/">Maven Repository</a> - <a href="http://ci.xephi.fr/plugin/repository/everything/">Maven Repository</a>
#####Statistics: - Statistics:
- bStats: [AuthMe on bstats.org](https://bstats.org/plugin/bukkit/AuthMe)
McStats: http://mcstats.org/plugin/AuthMe
<img src="http://i.mcstats.org/AuthMe/Global+Statistics.borderless.png">
<img src="http://i.mcstats.org/AuthMe/Rank.borderless.png">
<img src="http://i.mcstats.org/AuthMe/Version+Demographics.borderless.png">
<hr> <hr>
@ -92,7 +86,7 @@ You can also create your own translation file and, if you want, you can share it
<li>DoubleSaltedMD5: SALTED2MD5</li> <li>DoubleSaltedMD5: SALTED2MD5</li>
<li>WordPress: WORDPRESS</li> <li>WordPress: WORDPRESS</li>
</ul></li> </ul></li>
<li>Custom MySQL tables/columns names (useful with forums databases)</li> <li>Custom MySQL tables/columns names (useful with forum databases)</li>
<li><strong>Cached database queries!</strong></li> <li><strong>Cached database queries!</strong></li>
<li><strong>Fully compatible with Citizens2, CombatTag, CombatTagPlus!</strong></li> <li><strong>Fully compatible with Citizens2, CombatTag, CombatTagPlus!</strong></li>
<li>Compatible with Minecraft mods like <strong>BuildCraft or RedstoneCraft</strong></li> <li>Compatible with Minecraft mods like <strong>BuildCraft or RedstoneCraft</strong></li>

View File

@ -23,6 +23,7 @@ import javax.inject.Inject;
* @deprecated Use {@link NewAPI} * @deprecated Use {@link NewAPI}
*/ */
@Deprecated @Deprecated
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
public class API { public class API {
private static AuthMe instance; private static AuthMe instance;

View File

@ -24,6 +24,7 @@ import java.util.List;
* NewAPI authmeApi = AuthMe.getApi(); * NewAPI authmeApi = AuthMe.getApi();
* </code> * </code>
*/ */
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
public class NewAPI { public class NewAPI {
private static NewAPI singleton; private static NewAPI singleton;

View File

@ -19,6 +19,7 @@ import static java.util.Arrays.asList;
* {@code /authme} has a child whose label is {@code "register"}, then {@code /authme register} is the command that * {@code /authme} has a child whose label is {@code "register"}, then {@code /authme register} is the command that
* the child defines. * the child defines.
*/ */
@SuppressWarnings("checkstyle:FinalClass") // Justification: class is mocked in multiple tests
public class CommandDescription { public class CommandDescription {
/** /**

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.captcha;
import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.data.CaptchaManager; import fr.xephi.authme.data.CaptchaManager;
import fr.xephi.authme.data.auth.PlayerCache; import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.data.limbo.LimboCache; import fr.xephi.authme.data.limbo.LimboCache;
import fr.xephi.authme.message.MessageKey; import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.CommonService;

View File

@ -6,6 +6,8 @@ import fr.xephi.authme.settings.properties.DatabaseSettings;
/** /**
* Database column names. * Database column names.
*/ */
// Justification: String is immutable and this class is used to easily access the configurable column names
@SuppressWarnings({"checkstyle:VisibilityModifier", "checkstyle:MemberName", "checkstyle:AbbreviationAsWordInName"})
public final class Columns { public final class Columns {
public final String NAME; public final String NAME;

View File

@ -37,7 +37,7 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
// which is never the case when a converter is launched from the /authme converter command. // which is never the case when a converter is launched from the /authme converter command.
@Override @Override
public void execute(CommandSender sender) { public void execute(CommandSender sender) {
if (!destinationType.equals(destination.getType())) { if (destinationType != destination.getType()) {
if (sender != null) { if (sender != null) {
sender.sendMessage("Please configure your connection to " sender.sendMessage("Please configure your connection to "
+ destinationType + " and re-run this command"); + destinationType + " and re-run this command");
@ -59,6 +59,7 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
if (destination.isAuthAvailable(auth.getNickname())) { if (destination.isAuthAvailable(auth.getNickname())) {
skippedPlayers.add(auth.getNickname()); skippedPlayers.add(auth.getNickname());
} else { } else {
adaptPlayerAuth(auth);
destination.saveAuth(auth); destination.saveAuth(auth);
destination.updateQuitLoc(auth); destination.updateQuitLoc(auth);
} }
@ -72,6 +73,15 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
+ " to " + destinationType); + " to " + destinationType);
} }
/**
* Adapts the PlayerAuth from the source before it is saved in the destination.
*
* @param auth the auth from the source
*/
protected void adaptPlayerAuth(PlayerAuth auth) {
// noop
}
/** /**
* @return the data source to convert from * @return the data source to convert from
* @throws Exception during initialization of source * @throws Exception during initialization of source

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.datasource.converter; package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.FlatFile; import fr.xephi.authme.datasource.FlatFile;
@ -25,4 +26,11 @@ public class ForceFlatToSqlite extends AbstractDataSourceConverter<FlatFile> {
public FlatFile getSource() { public FlatFile getSource() {
return source; return source;
} }
@Override
protected void adaptPlayerAuth(PlayerAuth auth) {
// Issue #1120: FlatFile returns PlayerAuth objects with realname = lower-case name all the time.
// We don't want to take this over into the new data source.
auth.setRealName("Player");
}
} }

View File

@ -16,6 +16,7 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
/** /**
@ -40,19 +41,17 @@ public class RakamakConverter implements Converter {
@Override @Override
// TODO ljacqu 20151229: Restructure this into smaller portions // TODO ljacqu 20151229: Restructure this into smaller portions
public void execute(CommandSender sender) { public void execute(CommandSender sender) {
boolean useIP = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP); boolean useIp = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP);
String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME); String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME);
String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME); String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME);
File source = new File(pluginFolder, fileName); File source = new File(pluginFolder, fileName);
File ipfiles = new File(pluginFolder, ipFileName); File ipFiles = new File(pluginFolder, ipFileName);
HashMap<String, String> playerIP = new HashMap<>(); Map<String, String> playerIP = new HashMap<>();
HashMap<String, HashedPassword> playerPSW = new HashMap<>(); Map<String, HashedPassword> playerPassword = new HashMap<>();
try { try {
BufferedReader users; BufferedReader ipFile = new BufferedReader(new FileReader(ipFiles));
BufferedReader ipFile;
ipFile = new BufferedReader(new FileReader(ipfiles));
String line; String line;
if (useIP) { if (useIp) {
String tempLine; String tempLine;
while ((tempLine = ipFile.readLine()) != null) { while ((tempLine = ipFile.readLine()) != null) {
if (tempLine.contains("=")) { if (tempLine.contains("=")) {
@ -63,20 +62,20 @@ public class RakamakConverter implements Converter {
} }
ipFile.close(); ipFile.close();
users = new BufferedReader(new FileReader(source)); BufferedReader users = new BufferedReader(new FileReader(source));
while ((line = users.readLine()) != null) { while ((line = users.readLine()) != null) {
if (line.contains("=")) { if (line.contains("=")) {
String[] arguments = line.split("="); String[] arguments = line.split("=");
HashedPassword hashedPassword = passwordSecurity.computeHash(arguments[1], arguments[0]); HashedPassword hashedPassword = passwordSecurity.computeHash(arguments[1], arguments[0]);
playerPSW.put(arguments[0], hashedPassword); playerPassword.put(arguments[0], hashedPassword);
} }
} }
users.close(); users.close();
for (Entry<String, HashedPassword> m : playerPSW.entrySet()) { for (Entry<String, HashedPassword> m : playerPassword.entrySet()) {
String playerName = m.getKey(); String playerName = m.getKey();
HashedPassword psw = playerPSW.get(playerName); HashedPassword psw = playerPassword.get(playerName);
String ip = useIP ? playerIP.get(playerName) : "127.0.0.1"; String ip = useIp ? playerIP.get(playerName) : "127.0.0.1";
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(playerName) .name(playerName)
.realName(playerName) .realName(playerName)

View File

@ -45,6 +45,12 @@ public class OnStartupTasks {
OnStartupTasks() { OnStartupTasks() {
} }
/**
* Sends bstats metrics.
*
* @param plugin the plugin instance
* @param settings the settings
*/
public static void sendMetrics(AuthMe plugin, Settings settings) { public static void sendMetrics(AuthMe plugin, Settings settings) {
final Metrics metrics = new Metrics(plugin); final Metrics metrics = new Metrics(plugin);

View File

@ -111,7 +111,7 @@ class OnJoinVerifier implements Reloadable {
* @param event the login event to verify * @param event the login event to verify
* *
* @return true if the player's connection should be refused (i.e. the event does not need to be processed * @return true if the player's connection should be refused (i.e. the event does not need to be processed
* further), false if the player is not refused * further), false if the player is not refused
*/ */
public boolean refusePlayerForFullServer(PlayerLoginEvent event) { public boolean refusePlayerForFullServer(PlayerLoginEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();

View File

@ -14,6 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package fr.xephi.authme.listener.protocollib; package fr.xephi.authme.listener.protocollib;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
@ -46,7 +47,7 @@ class InventoryPacketAdapter extends PacketAdapter {
private static final int MAIN_SIZE = 27; private static final int MAIN_SIZE = 27;
private static final int HOTBAR_SIZE = 9; private static final int HOTBAR_SIZE = 9;
public InventoryPacketAdapter(AuthMe plugin) { InventoryPacketAdapter(AuthMe plugin) {
super(plugin, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS); super(plugin, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS);
} }

View File

@ -12,7 +12,7 @@ import fr.xephi.authme.data.auth.PlayerCache;
class TabCompletePacketAdapter extends PacketAdapter { class TabCompletePacketAdapter extends PacketAdapter {
public TabCompletePacketAdapter(AuthMe plugin) { TabCompletePacketAdapter(AuthMe plugin) {
super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.TAB_COMPLETE); super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.TAB_COMPLETE);
} }

View File

@ -31,7 +31,8 @@ public class PermissionsBukkitHandler implements PermissionHandler {
@Override @Override
public boolean addToGroup(Player player, String group) { public boolean addToGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player addgroup " + player.getName() + " " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player addgroup " + player.getName() + " " + group);
} }
@Override @Override
@ -46,17 +47,19 @@ public class PermissionsBukkitHandler implements PermissionHandler {
@Override @Override
public boolean removeFromGroup(Player player, String group) { public boolean removeFromGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player removegroup " + player.getName() + " " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player removegroup " + player.getName() + " " + group);
} }
@Override @Override
public boolean setGroup(Player player, String group) { public boolean setGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player setgroup " + player.getName() + " " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player setgroup " + player.getName() + " " + group);
} }
@Override @Override
public List<String> getGroups(Player player) { public List<String> getGroups(Player player) {
List<String> groups = new ArrayList<String>(); List<String> groups = new ArrayList<>();
for (Group group : permissionsBukkitInstance.getGroups(player.getUniqueId())) { for (Group group : permissionsBukkitInstance.getGroups(player.getUniqueId())) {
groups.add(group.getName()); groups.add(group.getName());
} }

View File

@ -30,7 +30,8 @@ public class ZPermissionsHandler implements PermissionHandler {
@Override @Override
public boolean addToGroup(Player player, String group) { public boolean addToGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player " + player.getName() + " addgroup " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player " + player.getName() + " addgroup " + group);
} }
@Override @Override
@ -41,20 +42,23 @@ public class ZPermissionsHandler implements PermissionHandler {
@Override @Override
public boolean hasPermissionOffline(String name, PermissionNode node) { public boolean hasPermissionOffline(String name, PermissionNode node) {
Map<String, Boolean> perms = zPermissionsService.getPlayerPermissions(null, null, name); Map<String, Boolean> perms = zPermissionsService.getPlayerPermissions(null, null, name);
if (perms.containsKey(node.getNode())) if (perms.containsKey(node.getNode())) {
return perms.get(node.getNode()); return perms.get(node.getNode());
else } else {
return false; return false;
}
} }
@Override @Override
public boolean removeFromGroup(Player player, String group) { public boolean removeFromGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player " + player.getName() + " removegroup " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player " + player.getName() + " removegroup " + group);
} }
@Override @Override
public boolean setGroup(Player player, String group) { public boolean setGroup(Player player, String group) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "permissions player " + player.getName() + " setgroup " + group); return Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
"permissions player " + player.getName() + " setgroup " + group);
} }
@Override @Override

View File

@ -56,10 +56,10 @@ class PasswordRegisterExecutorProvider {
/** Registration executor for password registration. */ /** Registration executor for password registration. */
class PasswordRegisterExecutor implements RegistrationExecutor { class PasswordRegisterExecutor implements RegistrationExecutor {
protected final Player player; private final Player player;
private final String password; private final String password;
private final String email; private final String email;
protected HashedPassword hashedPassword; private HashedPassword hashedPassword;
/** /**
* Constructor. * Constructor.
@ -105,6 +105,14 @@ class PasswordRegisterExecutorProvider {
} }
syncProcessManager.processSyncPasswordRegister(player); syncProcessManager.processSyncPasswordRegister(player);
} }
protected Player getPlayer() {
return player;
}
protected HashedPassword getHashedPassword() {
return hashedPassword;
}
} }
/** Executor for password registration via API call. */ /** Executor for password registration via API call. */
@ -147,8 +155,9 @@ class PasswordRegisterExecutorProvider {
public void executePostPersistAction() { public void executePostPersistAction() {
super.executePostPersistAction(); super.executePostPersistAction();
String qrCodeUrl = TwoFactor.getQRBarcodeURL(player.getName(), Bukkit.getIp(), hashedPassword.getHash()); String hash = getHashedPassword().getHash();
commonService.send(player, MessageKey.TWO_FACTOR_CREATE, hashedPassword.getHash(), qrCodeUrl); String qrCodeUrl = TwoFactor.getQRBarcodeURL(getPlayer().getName(), Bukkit.getIp(), hash);
commonService.send(getPlayer(), MessageKey.TWO_FACTOR_CREATE, hash, qrCodeUrl);
} }
} }

View File

@ -8,15 +8,15 @@ public abstract class SeparateSaltMethod implements EncryptionMethod {
@Override @Override
public abstract String computeHash(String password, String salt, String name); public abstract String computeHash(String password, String salt, String name);
@Override
public abstract String generateSalt();
@Override @Override
public HashedPassword computeHash(String password, String name) { public HashedPassword computeHash(String password, String name) {
String salt = generateSalt(); String salt = generateSalt();
return new HashedPassword(computeHash(password, salt, name), salt); return new HashedPassword(computeHash(password, salt, name), salt);
} }
@Override
public abstract String generateSalt();
@Override @Override
public boolean comparePassword(String password, HashedPassword hashedPassword, String name) { public boolean comparePassword(String password, HashedPassword hashedPassword, String name) {
return hashedPassword.getHash().equals(computeHash(password, hashedPassword.getSalt(), null)); return hashedPassword.getHash().equals(computeHash(password, hashedPassword.getSalt(), null));

View File

@ -17,13 +17,13 @@ public abstract class UsernameSaltMethod implements EncryptionMethod {
public abstract HashedPassword computeHash(String password, String name); public abstract HashedPassword computeHash(String password, String name);
@Override @Override
public boolean comparePassword(String password, HashedPassword hashedPassword, String name) { public String computeHash(String password, String salt, String name) {
return hashedPassword.getHash().equals(computeHash(password, name).getHash()); return computeHash(password, name).getHash();
} }
@Override @Override
public String computeHash(String password, String salt, String name) { public boolean comparePassword(String password, HashedPassword hashedPassword, String name) {
return computeHash(password, name).getHash(); return hashedPassword.getHash().equals(computeHash(password, name).getHash());
} }
@Override @Override

View File

@ -13,7 +13,6 @@ import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
@ -172,7 +171,7 @@ public class BukkitService implements SettingsDependent {
* @return a BukkitTask that contains the id number * @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null * @throws IllegalArgumentException if plugin is null
* @throws IllegalStateException if this was already scheduled * @throws IllegalStateException if this was already scheduled
* @see BukkitScheduler#runTaskTimer(Plugin, Runnable, long, long) * @see BukkitScheduler#runTaskTimer(org.bukkit.plugin.Plugin, Runnable, long, long)
*/ */
public BukkitTask runTaskTimer(BukkitRunnable task, long delay, long period) { public BukkitTask runTaskTimer(BukkitRunnable task, long delay, long period) {
return task.runTaskTimer(authMe, delay, period); return task.runTaskTimer(authMe, delay, period);

View File

@ -6,7 +6,7 @@ import ch.jalu.configme.properties.Property;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class BackupSettings implements SettingsHolder { public final class BackupSettings implements SettingsHolder {
@Comment("Enable or disable automatic backup") @Comment("Enable or disable automatic backup")
public static final Property<Boolean> ENABLED = public static final Property<Boolean> ENABLED =

View File

@ -6,7 +6,7 @@ import ch.jalu.configme.properties.Property;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class ConverterSettings implements SettingsHolder { public final class ConverterSettings implements SettingsHolder {
@Comment("Rakamak file name") @Comment("Rakamak file name")
public static final Property<String> RAKAMAK_FILE_NAME = public static final Property<String> RAKAMAK_FILE_NAME =

View File

@ -7,7 +7,7 @@ import fr.xephi.authme.datasource.DataSourceType;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class DatabaseSettings implements SettingsHolder { public final class DatabaseSettings implements SettingsHolder {
@Comment({"What type of database do you want to use?", @Comment({"What type of database do you want to use?",
"Valid values: sqlite, mysql"}) "Valid values: sqlite, mysql"})

View File

@ -9,7 +9,7 @@ import java.util.List;
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty; import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class EmailSettings implements SettingsHolder { public final class EmailSettings implements SettingsHolder {
@Comment("Email SMTP server host") @Comment("Email SMTP server host")
public static final Property<String> SMTP_HOST = public static final Property<String> SMTP_HOST =

View File

@ -9,7 +9,7 @@ import java.util.List;
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty; import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class HooksSettings implements SettingsHolder { public final class HooksSettings implements SettingsHolder {
@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<Boolean> MULTIVERSE = public static final Property<Boolean> MULTIVERSE =

View File

@ -7,7 +7,7 @@ import fr.xephi.authme.output.LogLevel;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class PluginSettings implements SettingsHolder { public final class PluginSettings implements SettingsHolder {
@Comment({ @Comment({
"Do you want to enable the session feature?", "Do you want to enable the session feature?",

View File

@ -10,7 +10,7 @@ import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class ProtectionSettings implements SettingsHolder { public final class ProtectionSettings implements SettingsHolder {
@Comment("Enable some servers protection (country based login, antibot)") @Comment("Enable some servers protection (country based login, antibot)")
public static final Property<Boolean> ENABLE_PROTECTION = public static final Property<Boolean> ENABLE_PROTECTION =

View File

@ -6,7 +6,7 @@ import ch.jalu.configme.properties.Property;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class PurgeSettings implements SettingsHolder { public final class PurgeSettings implements SettingsHolder {
@Comment("If enabled, AuthMe automatically purges old, unused accounts") @Comment("If enabled, AuthMe automatically purges old, unused accounts")
public static final Property<Boolean> USE_AUTO_PURGE = public static final Property<Boolean> USE_AUTO_PURGE =

View File

@ -8,7 +8,7 @@ import fr.xephi.authme.process.register.RegistrationType;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class RegistrationSettings implements SettingsHolder { public final class RegistrationSettings implements SettingsHolder {
@Comment("Enable registration on the server?") @Comment("Enable registration on the server?")
public static final Property<Boolean> IS_ENABLED = public static final Property<Boolean> IS_ENABLED =
@ -42,7 +42,8 @@ public class RegistrationSettings implements SettingsHolder {
"EMAIL_MANDATORY = for password register: 2nd argument MUST be an email address" "EMAIL_MANDATORY = for password register: 2nd argument MUST be an email address"
}) })
public static final Property<RegisterSecondaryArgument> REGISTER_SECOND_ARGUMENT = public static final Property<RegisterSecondaryArgument> REGISTER_SECOND_ARGUMENT =
newProperty(RegisterSecondaryArgument.class, "settings.registration.secondArg", RegisterSecondaryArgument.CONFIRMATION); newProperty(RegisterSecondaryArgument.class, "settings.registration.secondArg",
RegisterSecondaryArgument.CONFIRMATION);
@Comment({ @Comment({
"Do we force kick a player after a successful registration?", "Do we force kick a player after a successful registration?",

View File

@ -10,7 +10,7 @@ import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty; import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class RestrictionSettings implements SettingsHolder { public final class RestrictionSettings implements SettingsHolder {
@Comment({ @Comment({
"Can not authenticated players chat?", "Can not authenticated players chat?",

View File

@ -12,7 +12,7 @@ import java.util.Set;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty; import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty; import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public class SecuritySettings implements SettingsHolder { public final class SecuritySettings implements SettingsHolder {
@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,", "Take care with this, if you set this to false,",
@ -86,7 +86,8 @@ public class SecuritySettings implements SettingsHolder {
"- 'password'", "- 'password'",
"- 'help'"}) "- 'help'"})
public static final Property<List<String>> UNSAFE_PASSWORDS = public static final Property<List<String>> UNSAFE_PASSWORDS =
newLowercaseListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321", "123456789", "help"); newLowercaseListProperty("settings.security.unsafePasswords",
"123456", "password", "qwerty", "12345", "54321", "123456789", "help");
@Comment("Tempban a user's IP address if they enter the wrong password too many times") @Comment("Tempban a user's IP address if they enter the wrong password too many times")
public static final Property<Boolean> TEMPBAN_ON_MAX_LOGINS = public static final Property<Boolean> TEMPBAN_ON_MAX_LOGINS =

View File

@ -24,7 +24,7 @@ public final class RandomStringUtils {
* @return The random string * @return The random string
*/ */
public static String generate(int length) { public static String generate(int length) {
return generate(length, LOWER_ALPHANUMERIC_INDEX); return generateString(length, LOWER_ALPHANUMERIC_INDEX);
} }
/** /**
@ -35,7 +35,7 @@ public final class RandomStringUtils {
* @return The random hexadecimal string * @return The random hexadecimal string
*/ */
public static String generateHex(int length) { public static String generateHex(int length) {
return generate(length, HEX_MAX_INDEX); return generateString(length, HEX_MAX_INDEX);
} }
/** /**
@ -46,10 +46,10 @@ public final class RandomStringUtils {
* @return The random string * @return The random string
*/ */
public static String generateLowerUpper(int length) { public static String generateLowerUpper(int length) {
return generate(length, CHARS.length); return generateString(length, CHARS.length);
} }
private static String generate(int length, int maxIndex) { private static String generateString(int length, int maxIndex) {
if (length < 0) { if (length < 0) {
throw new IllegalArgumentException("Length must be positive but was " + length); throw new IllegalArgumentException("Length must be positive but was " + length);
} }

View File

@ -11,7 +11,7 @@ import java.util.stream.Collectors;
* *
* @param <A> the argument type * @param <A> the argument type
*/ */
public class TagReplacer<A> { public final class TagReplacer<A> {
private final List<Tag<A>> tags; private final List<Tag<A>> tags;
private final Collection<String> messages; private final Collection<String> messages;

View File

@ -86,19 +86,19 @@ email_send_failure: 'Письмо не може быть отправлено.
show_no_email: '&2В данный момент к вашему аккаунте не привязана электронная почта.' show_no_email: '&2В данный момент к вашему аккаунте не привязана электронная почта.'
add_email: '&cДобавьте свой email: &e/email add <Ваш Email> <Ваш Email>' add_email: '&cДобавьте свой email: &e/email add <Ваш Email> <Ваш Email>'
recovery_email: '&cЗабыли пароль? Используйте &e/email recovery <Ваш Email>' recovery_email: '&cЗабыли пароль? Используйте &e/email recovery <Ваш Email>'
# TODO email_cooldown_error: '&cAn email was already sent recently. You must wait %time before you can send a new one.' email_cooldown_error: '&cЭлектронное письмо было отправлено недавно. Пожалуйста, подождите %time прежде чем отправить новое письмо.'
# Каптча # Каптча
usage_captcha: '&cВы должны ввести код, используйте: &e/captcha <theCaptcha>' usage_captcha: '&cВы должны ввести код, используйте: &e/captcha <theCaptcha>'
wrong_captcha: '&cНеверный код, используйте: &e/captcha THE_CAPTCHA' wrong_captcha: '&cНеверный код, используйте: &e/captcha THE_CAPTCHA'
valid_captcha: '&2Вы успешно ввели код!' valid_captcha: '&2Вы успешно ввели код!'
# Time units # Единицы времени
# TODO second: 'second' second: 'сек.'
# TODO seconds: 'seconds' seconds: 'сек.'
# TODO minute: 'minute' minute: 'мин.'
# TODO minutes: 'minutes' minutes: 'мин.'
# TODO hour: 'hour' hour: 'ч.'
# TODO hours: 'hours' hours: 'ч.'
# TODO day: 'day' day: 'дн.'
# TODO days: 'days' days: 'дн.'

View File

@ -61,13 +61,13 @@ public class FlatFileIntegrationTest {
// then // then
assertThat(authList, hasSize(7)); assertThat(authList, hasSize(7));
assertThat(getName("bobby", authList), hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")); assertThat(getName("bobby", authList), hasAuthBasicData("bobby", "bobby", "your@email.com", "123.45.67.89"));
assertThat(getName("bobby", authList), hasAuthLocation(1.05, 2.1, 4.2, "world")); assertThat(getName("bobby", authList), hasAuthLocation(1.05, 2.1, 4.2, "world"));
assertThat(getName("bobby", authList).getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966")); assertThat(getName("bobby", authList).getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966"));
assertThat(getName("twofields", authList), hasAuthBasicData("twofields", "twoFields", "your@email.com", "127.0.0.1")); assertThat(getName("twofields", authList), hasAuthBasicData("twofields", "twofields", "your@email.com", "127.0.0.1"));
assertThat(getName("twofields", authList).getPassword(), equalToHash("hash1234")); assertThat(getName("twofields", authList).getPassword(), equalToHash("hash1234"));
assertThat(getName("threefields", authList), hasAuthBasicData("threefields", "threeFields", "your@email.com", "33.33.33.33")); assertThat(getName("threefields", authList), hasAuthBasicData("threefields", "threefields", "your@email.com", "33.33.33.33"));
assertThat(getName("fourfields", authList), hasAuthBasicData("fourfields", "fourFields", "your@email.com", "4.4.4.4")); assertThat(getName("fourfields", authList), hasAuthBasicData("fourfields", "fourfields", "your@email.com", "4.4.4.4"));
assertThat(getName("fourfields", authList).getLastLogin(), equalTo(404040404L)); assertThat(getName("fourfields", authList).getLastLogin(), equalTo(404040404L));
assertThat(getName("sevenfields", authList), hasAuthLocation(7.7, 14.14, 21.21, "world")); assertThat(getName("sevenfields", authList), hasAuthLocation(7.7, 14.14, 21.21, "world"));
assertThat(getName("eightfields", authList), hasAuthLocation(8.8, 17.6, 26.4, "eightworld")); assertThat(getName("eightfields", authList), hasAuthLocation(8.8, 17.6, 26.4, "eightworld"));

View File

@ -63,11 +63,11 @@ public class ForceFlatToSqliteTest {
ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class); ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);
verify(dataSource, times(7)).saveAuth(authCaptor.capture()); verify(dataSource, times(7)).saveAuth(authCaptor.capture());
List<PlayerAuth> auths = authCaptor.getAllValues(); List<PlayerAuth> auths = authCaptor.getAllValues();
assertThat(auths, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89"))); assertThat(auths, hasItem(hasAuthBasicData("bobby", "Player", "your@email.com", "123.45.67.89")));
assertThat(auths, hasItem(hasAuthLocation(1.05, 2.1, 4.2, "world"))); assertThat(auths, hasItem(hasAuthLocation(1.05, 2.1, 4.2, "world")));
assertThat(auths, hasItem(hasAuthBasicData("user", "user", "user@example.org", "34.56.78.90"))); assertThat(auths, hasItem(hasAuthBasicData("user", "Player", "user@example.org", "34.56.78.90")));
assertThat(auths, hasItem(hasAuthLocation(124.1, 76.3, -127.8, "nether"))); assertThat(auths, hasItem(hasAuthLocation(124.1, 76.3, -127.8, "nether")));
assertThat(auths, hasItem(hasAuthBasicData("eightfields", "eightFields", "your@email.com", "6.6.6.66"))); assertThat(auths, hasItem(hasAuthBasicData("eightfields", "Player", "your@email.com", "6.6.6.66")));
assertThat(auths, hasItem(hasAuthLocation(8.8, 17.6, 26.4, "eightworld"))); assertThat(auths, hasItem(hasAuthLocation(8.8, 17.6, 26.4, "eightworld")));
} }

View File

@ -1,7 +1,7 @@
Bobby:$SHA$11aa0706173d7272$dbba966:123.45.67.89:1449136800:1.05:2.1:4.2:world:your@email.com bobby:$SHA$11aa0706173d7272$dbba966:123.45.67.89:1449136800:1.05:2.1:4.2:world:your@email.com
user:b28c32f624a4eb161d6adc9acb5bfc5b:34.56.78.90:1453242857:124.1:76.3:-127.8:nether:user@example.org user:b28c32f624a4eb161d6adc9acb5bfc5b:34.56.78.90:1453242857:124.1:76.3:-127.8:nether:user@example.org
twoFields:hash1234 twofields:hash1234
threeFields:hash369:33.33.33.33 threefields:hash369:33.33.33.33
fourFields:$hash$4444:4.4.4.4:404040404 fourfields:$hash$4444:4.4.4.4:404040404
sevenFields:hash7749:5.5.5.55:1414141414:7.7:14.14:21.21 sevenfields:hash7749:5.5.5.55:1414141414:7.7:14.14:21.21
eightFields:hash8168:6.6.6.66:1234567888:8.8:17.6:26.4:eightworld eightfields:hash8168:6.6.6.66:1234567888:8.8:17.6:26.4:eightworld