src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java
package fr.xephi.authme.api.v3;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.GeoIpService;
import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
/**
* The current API of AuthMe.
*
* Recommended method of retrieving the AuthMeApi object:
* <code>
* AuthMeApi authmeApi = AuthMeApi.getInstance();
* </code>
*/
public class AuthMeApi {
private static AuthMeApi singleton;
private final AuthMe plugin;
private final DataSource dataSource;
private final PasswordSecurity passwordSecurity;
private final Management management;
private final ValidationService validationService;
private final PlayerCache playerCache;
private final GeoIpService geoIpService;
/*
* Constructor for AuthMeApi.
*/
@Inject
AuthMeApi(AuthMe plugin, DataSource dataSource, PlayerCache playerCache, PasswordSecurity passwordSecurity,
Management management, ValidationService validationService, GeoIpService geoIpService) {
this.plugin = plugin;
this.dataSource = dataSource;
this.passwordSecurity = passwordSecurity;
this.management = management;
this.validationService = validationService;
this.playerCache = playerCache;
this.geoIpService = geoIpService;
AuthMeApi.singleton = this;
}
/**
* Get the AuthMeApi object for AuthMe.
*
* @return The AuthMeApi object, or null if the AuthMe plugin is not enabled or not fully initialized yet
*/
public static AuthMeApi getInstance() {
return singleton;
}
/**
* Return the plugin instance.
*
* @return The AuthMe instance
*/
public AuthMe getPlugin() {
return plugin;
}
/**
* Gather the version number of the plugin.
* This can be used to determine whether certain AuthMeApi features are available or not.
*
* @return Plugin version identifier as a string.
*/
public String getPluginVersion() {
return AuthMe.getPluginVersion();
}
/**
* Return whether the given player is authenticated.
*
* @param player The player to verify
* @return true if the player is authenticated
*/
public boolean isAuthenticated(Player player) {
return playerCache.isAuthenticated(player.getName());
}
/**
* Check whether the given player is an NPC.
*
* @param player The player to verify
* @return true if the player is an npc
*/
public boolean isNpc(Player player) {
return PlayerUtils.isNpc(player);
}
/**
* Check whether the given player is unrestricted. For such players, AuthMe will not require
* them to authenticate.
*
* @param player The player to verify
* @return true if the player is unrestricted
* @see fr.xephi.authme.settings.properties.RestrictionSettings#UNRESTRICTED_NAMES
*/
public boolean isUnrestricted(Player player) {
return validationService.isUnrestricted(player.getName());
}
/**
* Get the last location of an online player.
*
* @param player The player to process
* @return The location of the player
*/
public Location getLastLocation(Player player) {
PlayerAuth auth = playerCache.getAuth(player.getName());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()),
auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getYaw(), auth.getPitch());
}
return null;
}
/**
* Returns the AuthMe info of the given player's name, or empty optional if the player doesn't exist.
*
* @param playerName The player name to look up
* @return AuthMe player info, or empty optional if the player doesn't exist
*/
public Optional<AuthMePlayer> getPlayerInfo(String playerName) {
PlayerAuth auth = playerCache.getAuth(playerName);
if (auth == null) {
auth = dataSource.getAuth(playerName);
}
return AuthMePlayerImpl.fromPlayerAuth(auth);
}
/**
* Get the last ip address of a player.
*
* @param playerName The name of the player to process
* @return The last ip address of the player
*/
public String getLastIp(String playerName) {
PlayerAuth auth = playerCache.getAuth(playerName);
if (auth == null) {
auth = dataSource.getAuth(playerName);
}
if (auth != null) {
return auth.getLastIp();
}
return null;
}
/**
* Get user names by ip.
*
* @param address The ip address to process
* @return The list of user names related to the ip address
*/
public List<String> getNamesByIp(String address) {
return dataSource.getAllAuthsByIp(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)}
*/
@Deprecated
public Date getLastLogin(String playerName) {
Long lastLogin = getLastLoginMillis(playerName);
return lastLogin == null ? null : new Date(lastLogin);
}
/**
* Get the last (AuthMe) login timestamp of a player.
*
* @param playerName The name of the player to process
*
* @return The timestamp of the last login, or null if the player doesn't exist or has never logged in
*/
public Instant getLastLoginTime(String playerName) {
Long lastLogin = getLastLoginMillis(playerName);
return lastLogin == null ? null : Instant.ofEpochMilli(lastLogin);
}
private Long getLastLoginMillis(String playerName) {
PlayerAuth auth = playerCache.getAuth(playerName);
if (auth == null) {
auth = dataSource.getAuth(playerName);
}
if (auth != null) {
return auth.getLastLogin();
}
return null;
}
/**
* Return whether the player is registered.
*
* @param playerName The player name to check
* @return true if player is registered, false otherwise
*/
public boolean isRegistered(String playerName) {
String player = playerName.toLowerCase(Locale.ROOT);
return dataSource.isAuthAvailable(player);
}
/**
* Check the password for the given player.
*
* @param playerName The player to check the password for
* @param passwordToCheck The password to check
* @return true if the password is correct, false otherwise
*/
public boolean checkPassword(String playerName, String passwordToCheck) {
return passwordSecurity.comparePassword(passwordToCheck, playerName);
}
/**
* Register an OFFLINE/ONLINE player with the given password.
*
* @param playerName The player to register
* @param password The password to register the player with
*
* @return true if the player was registered successfully
*/
public boolean registerPlayer(String playerName, String password) {
String name = playerName.toLowerCase(Locale.ROOT);
if (isRegistered(name)) {
return false;
}
HashedPassword result = passwordSecurity.computeHash(password, name);
PlayerAuth auth = PlayerAuth.builder()
.name(name)
.password(result)
.realName(playerName)
.registrationDate(System.currentTimeMillis())
.build();
return dataSource.saveAuth(auth);
}
/**
* Force a player to login, i.e. the player is logged in without needing his password.
*
* @param player The player to log in
*/
public void forceLogin(Player player) {
management.forceLogin(player);
}
/**
* Force a player to logout.
*
* @param player The player to log out
*/
public void forceLogout(Player player) {
management.performLogout(player);
}
/**
* Force an ONLINE player to register.
*
* @param player The player to register
* @param password The password to use
* @param autoLogin Should the player be authenticated automatically after the registration?
*/
public void forceRegister(Player player, String password, boolean autoLogin) {
management.performRegister(RegistrationMethod.API_REGISTRATION,
ApiPasswordRegisterParams.of(player, password, autoLogin));
}
/**
* Register an ONLINE player with the given password.
*
* @param player The player to register
* @param password The password to use
*/
public void forceRegister(Player player, String password) {
forceRegister(player, password, true);
}
/**
* Unregister a player from AuthMe.
*
* @param player The player to unregister
*/
public void forceUnregister(Player player) {
management.performUnregisterByAdmin(null, player.getName(), player);
}
/**
* Unregister a player from AuthMe by name.
*
* @param name the name of the player (case-insensitive)
*/
public void forceUnregister(String name) {
management.performUnregisterByAdmin(null, name, Bukkit.getPlayer(name));
}
/**
* Change a user's password
*
* @param name the user name
* @param newPassword the new password
*/
public void changePassword(String name, String newPassword) {
management.performPasswordChangeAsAdmin(null, name, newPassword);
}
/**
* Get all the registered names (lowercase)
*
* @return registered names
*/
public List<String> getRegisteredNames() {
List<String> registeredNames = new ArrayList<>();
dataSource.getAllAuths().forEach(auth -> registeredNames.add(auth.getNickname()));
return registeredNames;
}
/**
* Get all the registered real-names (original case)
*
* @return registered real-names
*/
public List<String> getRegisteredRealNames() {
List<String> registeredNames = new ArrayList<>();
dataSource.getAllAuths().forEach(auth -> registeredNames.add(auth.getRealName()));
return registeredNames;
}
/**
* Get the country code of the given IP address.
*
* @param ip textual IP address to lookup.
*
* @return two-character ISO 3166-1 alpha code for the country.
*/
public String getCountryCode(String ip) {
return geoIpService.getCountryCode(ip);
}
/**
* Get the country name of the given IP address.
*
* @param ip textual IP address to lookup.
*
* @return The name of the country.
*/
public String getCountryName(String ip) {
return geoIpService.getCountryName(ip);
}
}