Merge branch 'master' into 745-captcha-login-message
This commit is contained in:
commit
fae7286776
83
README.md
83
README.md
@ -1,32 +1,28 @@
|
|||||||
<p align="center"><img src="http://i61.tinypic.com/291dm49.png"></p>
|
<p align="center"><img src="http://i61.tinypic.com/291dm49.png"></p>
|
||||||
<p align="center"><strong>The most used authentication plugin for CraftBukkit/Spigot!</strong></p>
|
<p align="center"><strong>The most used authentication plugin for Spigot and CraftBukkit!</strong></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
#####Development tools:
|
#####Links and Contacts:
|
||||||
|
|
||||||
- MAIN REPO (**release sources, issue tracker!**): [Github Main Page](https://github.com/Xephi/AuthMeReloaded)
|
- GitHub pages:
|
||||||
|
- [Main](https://github.com/Xephi/AuthMeReloaded) (**release sources, issue tracker!**)
|
||||||
|
- [Development](https://github.com/AuthMe/AuthMeReloaded) (**latest sources, please send PRs here!**):
|
||||||
|
|
||||||
- DEVELOPMENT TEAM REPO (**latest sources, please send PRs here!**): [Github Development Page](https://github.com/AuthMe/AuthMeReloaded)
|
- Contacts:
|
||||||
|
- [](https://gitter.im/Xephi/AuthMeReloaded?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
- Developers ChatRoom: [](https://gitter.im/Xephi/AuthMeReloaded?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
- CI Services:
|
||||||
|
- [Official Jenkins](http://ci.xephi.fr/job/AuthMeReloaded) (**DEVELOPMENT BUILDS**)
|
||||||
|
- Travis CI: [](https://travis-ci.org/AuthMe/AuthMeReloaded)
|
||||||
|
- CircleCI: [](https://circleci.com/gh/AuthMe/AuthMeReloaded)
|
||||||
|
|
||||||
- Build Server (**DEVELOPMENT BUILDS**): [Xephi's Jenkins](http://ci.xephi.fr/job/AuthMeReloaded)
|
- Project status:
|
||||||
|
- Dependencies: [](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d)
|
||||||
|
- Test coverage: [](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master)
|
||||||
|
|
||||||
- Build status: [](https://travis-ci.org/AuthMe/AuthMeReloaded)
|
- Development resources:
|
||||||
|
- <a href="http://ci.xephi.fr/job/AuthMeReloaded/javadoc/">JavaDocs</a>
|
||||||
- Dependencies: [](https://www.versioneye.com/user/projects/57b182e8d6ffcd0032d7cf2d)
|
- <a href="http://ci.xephi.fr/plugin/repository/everything/">Maven Repository</a>
|
||||||
|
|
||||||
- Build status (CircleCI): [](https://circleci.com/gh/AuthMe/AuthMeReloaded)
|
|
||||||
- Alternative Dev Build download link (via CircleCi): <a href="https://circleci-tkn.rhcloud.com/api/v1/project/AuthMe/AuthMeReloaded/tree/master/latest/artifacts/AuthMe.jar">Download</a>
|
|
||||||
- JitPack (just in case): [](https://jitpack.io/#AuthMe/AuthMeReloaded)
|
|
||||||
|
|
||||||
- Code Coverage: [](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master)
|
|
||||||
|
|
||||||
- Issue Tracking : [](https://waffle.io/Xephi/AuthMeReloaded) [](https://waffle.io/Xephi/AuthMeReloaded) [](https://waffle.io/Xephi/AuthMeReloaded)
|
|
||||||
|
|
||||||
- JavaDoc: <a href="http://ci.xephi.fr/job/AuthMeReloaded/javadoc/">AuthMe Javadoc</a>
|
|
||||||
|
|
||||||
- Maven Repo: <a href="http://ci.xephi.fr/plugin/repository/everything/">AuthMe Repo</a>
|
|
||||||
|
|
||||||
#####Statistics:
|
#####Statistics:
|
||||||
|
|
||||||
@ -38,25 +34,21 @@ McStats: http://mcstats.org/plugin/AuthMe
|
|||||||
|
|
||||||
<img src="http://i.mcstats.org/AuthMe/Version+Demographics.borderless.png">
|
<img src="http://i.mcstats.org/AuthMe/Version+Demographics.borderless.png">
|
||||||
|
|
||||||
#####Development history:
|
|
||||||
Outdated!
|
|
||||||
[](https://www.youtube.com/watch?v=hJRzNfYyd9k)
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
#####Compiling Requirements:
|
#####Compiling requirements:
|
||||||
>- JDK 1.8
|
>- JDK 1.8
|
||||||
>- Maven
|
>- Maven
|
||||||
>- Git/Github (Optional)
|
>- Git/Github (Optional)
|
||||||
|
|
||||||
#####How to compile the project:
|
#####How to compile the project:
|
||||||
>- Clone the project with Git/Github
|
>- Clone the project with Git/Github
|
||||||
>- Execute command "mvn clean install"
|
>- Execute command "mvn clean package"
|
||||||
|
|
||||||
#####Running Requirements:
|
#####Running requirements:
|
||||||
>- Java 1.8
|
>- Java 1.8
|
||||||
>- PaperSpigot, Spigot or CraftBukkit (1.7.10, 1.8.X, 1.9.X, 1.10.X)
|
>- TacoSpigot, PaperSpigot, Spigot or CraftBukkit (1.7.10, 1.8.X, 1.9.X, 1.10.X, 1.11.X)
|
||||||
>- ProtocolLib (optional, required by the protectInventory feature)
|
>- ProtocolLib (optional, required by some features)
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
###Plugin Description:
|
###Plugin Description:
|
||||||
@ -102,19 +94,19 @@ You can also create your own translation file and, if you want, you can share it
|
|||||||
</ul></li>
|
</ul></li>
|
||||||
<li>Custom MySQL tables/columns names (useful with forums databases)</li>
|
<li>Custom MySQL tables/columns names (useful with forums databases)</li>
|
||||||
<li><strong>Cached database queries!</strong></li>
|
<li><strong>Cached database queries!</strong></li>
|
||||||
<li><strong>Fully compatible with Citizens2, CombatTag, CombatTagPlus and ChestShop!</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>
|
||||||
<li>Restricted users (associate a Username with an IP)</li>
|
<li>Restricted users (associate a username with an IP)</li>
|
||||||
<li>Protect player's inventory until a correct Authentication</li>
|
<li>Protect player's inventory until correct authentication (requires ProtocolLib)</li>
|
||||||
<li>Saves the quit location of the player</li>
|
<li>Saves the quit location of the player</li>
|
||||||
<li>Automatic database Backup</li>
|
<li>Automatic database backup</li>
|
||||||
<li>Available languages: en, de, br, cz, pl, fr, uk, ru, hu, sk, es, fi, zhtw, zhhk, zhcn, lt, it, ko, pt, nl, gl, bg, eu, tr, vn (feel free to send new translations)</li>
|
<li>Available languages: <a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md">translations</a></li>
|
||||||
<li>Built-in Deprecated FlatFile (auths.db) to SQL (authme.sql) converter!</li>
|
<li>Built-in Deprecated FlatFile (auths.db) to SQL (authme.sql) converter!</li>
|
||||||
<li><strong>Import your old database from other plugins like Rakamak, xAuth, CrazyLogin, RoyalAuth and vAuth!</strong></li>
|
<li><strong>Import your old database from other plugins like Rakamak, xAuth, CrazyLogin, RoyalAuth and vAuth!</strong></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
####Configuration
|
####Configuration
|
||||||
<a href="http://dev.bukkit.org/server-mods/authme-reloaded/pages/configure-auth-me/">How to Configure Authme</a>
|
<a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/config.md">How to configure Authme</a>
|
||||||
####Email Recovery Dependency
|
####Email Recovery Dependency
|
||||||
<a href="http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-configure-email-recovery-system/">How to configure email recovery system?</a>
|
<a href="http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-configure-email-recovery-system/">How to configure email recovery system?</a>
|
||||||
####Commands
|
####Commands
|
||||||
@ -125,30 +117,21 @@ You can also create your own translation file and, if you want, you can share it
|
|||||||
- [List of all permission nodes](http://github.com/AuthMe-Team/AuthMeReloaded/blob/master/docs/permission_nodes.md)
|
- [List of all permission nodes](http://github.com/AuthMe-Team/AuthMeReloaded/blob/master/docs/permission_nodes.md)
|
||||||
|
|
||||||
####How To
|
####How To
|
||||||
- [How to install and set up](http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-install-and-initial-configuration/)
|
|
||||||
- [How to import database from xAuth](http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-import-database-from-xauth/)
|
- [How to import database from xAuth](http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-import-database-from-xauth/)
|
||||||
- [Website integration](http://dev.bukkit.org/server-mods/authme-reloaded/pages/web-site-integration/)
|
- [Website integration](http://dev.bukkit.org/server-mods/authme-reloaded/pages/web-site-integration/)
|
||||||
- [Click here for an example of the config file](https://raw.githubusercontent.com/Xephi/AuthMeReloaded/master/src/main/resources/config.yml)
|
|
||||||
- [How to convert from Rakamak](http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-import-database-from-rakamak/)
|
- [How to convert from Rakamak](http://dev.bukkit.org/server-mods/authme-reloaded/pages/how-to-import-database-from-rakamak/)
|
||||||
- Convert from FlatFile (auths.db but not the sqlite one) to MySQL: /authme converter
|
- Convert between database types (e.g. SQLite to MySQL): /authme converter
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
#####GeoIP
|
|
||||||
This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
#####Donate
|
|
||||||
<p>Do you like our work? Do you want to buy us a coffee? :)<br>
|
|
||||||
EUR: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QLMM9SNCX825Y"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif"></a>
|
|
||||||
USD: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PWQMYCP2SAH6L"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif"></a></p>
|
|
||||||
|
|
||||||
#####Sponsor
|
#####Sponsor
|
||||||
GameHosting.it is leader in Italy as Game Server Provider. With its own DataCenter offers Anti-DDoS solutions at affordable prices. Game Server of Minecraft based on Multicraft are equipped with the latest technology in hardware.
|
GameHosting.it is leader in Italy as Game Server Provider. With its own DataCenter offers Anti-DDoS solutions at affordable prices. Game Server of Minecraft based on Multicraft are equipped with the latest technology in hardware.
|
||||||
[](http://www.gamehosting.it)
|
[](http://www.gamehosting.it)
|
||||||
|
|
||||||
#####Credits
|
#####Credits
|
||||||
<p>Team members: look at the <a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/team.txt">team.txt file</a>
|
<p>Team members: look at the <a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/team.txt">member list</a>
|
||||||
<p>Credit for old version of the plugin to: d4rkwarriors, fabe1337, Whoami2 and pomo4ka</p>
|
<p>Credit for old version of the plugin to: d4rkwarriors, fabe1337, Whoami2 and pomo4ka</p>
|
||||||
<p>Thanks also to: AS1LV3RN1NJA, Hoeze and eprimex</p>
|
<p>Thanks also to: AS1LV3RN1NJA, Hoeze and eprimex</p>
|
||||||
|
|
||||||
|
#####GeoIP License
|
||||||
|
This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com
|
||||||
|
|||||||
@ -11,6 +11,8 @@ test:
|
|||||||
- cp ./target/AuthMe-*-SNAPSHOT-spigot.jar $CIRCLE_ARTIFACTS
|
- cp ./target/AuthMe-*-SNAPSHOT-spigot.jar $CIRCLE_ARTIFACTS
|
||||||
- cp ./target/AuthMe-*-SNAPSHOT-legacy.jar $CIRCLE_ARTIFACTS
|
- cp ./target/AuthMe-*-SNAPSHOT-legacy.jar $CIRCLE_ARTIFACTS
|
||||||
- cp ./target/AuthMe-*-SNAPSHOT-spigot.jar $CIRCLE_ARTIFACTS/AuthMe.jar
|
- cp ./target/AuthMe-*-SNAPSHOT-spigot.jar $CIRCLE_ARTIFACTS/AuthMe.jar
|
||||||
|
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
|
||||||
|
- find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||||
notify:
|
notify:
|
||||||
webhooks:
|
webhooks:
|
||||||
- url: https://webhooks.gitter.im/e/7b92ac1a1741748b26bf
|
- url: https://webhooks.gitter.im/e/7b92ac1a1741748b26bf
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sun Oct 16 21:39:08 CEST 2016. See commands/commands.tpl.md -->
|
<!-- File auto-generated on Sun Oct 23 18:25:12 CEST 2016. See docs/commands/commands.tpl.md -->
|
||||||
|
|
||||||
## AuthMe Commands
|
## AuthMe Commands
|
||||||
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
|
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
|
||||||
@ -63,7 +63,8 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||||||
- **/changepassword** <oldPassword> <newPassword>: Command to change your password using AuthMeReloaded.
|
- **/changepassword** <oldPassword> <newPassword>: Command to change your password using AuthMeReloaded.
|
||||||
<br />Requires `authme.player.changepassword`
|
<br />Requires `authme.player.changepassword`
|
||||||
- **/changepassword help** [query]: View detailed help for /changepassword commands.
|
- **/changepassword help** [query]: View detailed help for /changepassword commands.
|
||||||
- **/email**: The AuthMeReloaded Email command base.
|
- **/email**: The AuthMeReloaded email command base.
|
||||||
|
- **/email show**: Show your current email address.
|
||||||
- **/email add** <email> <verifyEmail>: Add a new email address to your account.
|
- **/email add** <email> <verifyEmail>: Add a new email address to your account.
|
||||||
<br />Requires `authme.player.email.add`
|
<br />Requires `authme.player.email.add`
|
||||||
- **/email change** <oldEmail> <newEmail>: Change an email address of your account.
|
- **/email change** <oldEmail> <newEmail>: Change an email address of your account.
|
||||||
@ -75,7 +76,6 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||||||
<br />Requires `authme.player.captcha`
|
<br />Requires `authme.player.captcha`
|
||||||
- **/captcha help** [query]: View detailed help for /captcha commands.
|
- **/captcha help** [query]: View detailed help for /captcha commands.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 16 21:39:08 CEST 2016
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 23 18:25:12 CEST 2016
|
||||||
|
|||||||
467
docs/config.md
Normal file
467
docs/config.md
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
|
<!-- File auto-generated on Sun Nov 13 13:34:49 CET 2016. See docs/config/config.tpl.md -->
|
||||||
|
|
||||||
|
## AuthMe Configuration
|
||||||
|
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||||
|
with which you can configure various settings. This following is the initial contents of
|
||||||
|
the generated config.yml file.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
|
||||||
|
DataSource:
|
||||||
|
# What type of database do you want to use?
|
||||||
|
# Valid values: sqlite, mysql
|
||||||
|
backend: 'SQLITE'
|
||||||
|
# Enable database caching, should improve database performance
|
||||||
|
caching: true
|
||||||
|
# Database host address
|
||||||
|
mySQLHost: '127.0.0.1'
|
||||||
|
# Database port
|
||||||
|
mySQLPort: '3306'
|
||||||
|
# Username about Database Connection Infos
|
||||||
|
mySQLUsername: 'authme'
|
||||||
|
# Password about Database Connection Infos
|
||||||
|
mySQLPassword: '12345'
|
||||||
|
# Database Name, use with converters or as SQLITE database name
|
||||||
|
mySQLDatabase: 'authme'
|
||||||
|
# Table of the database
|
||||||
|
mySQLTablename: 'authme'
|
||||||
|
# Column of IDs to sort data
|
||||||
|
mySQLColumnId: 'id'
|
||||||
|
# Column for storing or checking players nickname
|
||||||
|
mySQLColumnName: 'username'
|
||||||
|
# Column for storing or checking players RealName
|
||||||
|
mySQLRealName: 'realname'
|
||||||
|
# Column for storing players passwords
|
||||||
|
mySQLColumnPassword: 'password'
|
||||||
|
# Column for storing players emails
|
||||||
|
mySQLColumnEmail: 'email'
|
||||||
|
# Column for storing if a player is logged in or not
|
||||||
|
mySQLColumnLogged: 'isLogged'
|
||||||
|
# Column for storing players ips
|
||||||
|
mySQLColumnIp: 'ip'
|
||||||
|
# Column for storing players lastlogins
|
||||||
|
mySQLColumnLastLogin: 'lastlogin'
|
||||||
|
# Column for storing player LastLocation - X
|
||||||
|
mySQLlastlocX: 'x'
|
||||||
|
# Column for storing player LastLocation - Y
|
||||||
|
mySQLlastlocY: 'y'
|
||||||
|
# Column for storing player LastLocation - Z
|
||||||
|
mySQLlastlocZ: 'z'
|
||||||
|
# Column for storing player LastLocation - World Name
|
||||||
|
mySQLlastlocWorld: 'world'
|
||||||
|
# Overrides the size of the DB Connection Pool, -1 = Auto
|
||||||
|
poolSize: -1
|
||||||
|
ExternalBoardOptions:
|
||||||
|
# Column for storing players passwords salts
|
||||||
|
mySQLColumnSalt: ''
|
||||||
|
# Column for storing players groups
|
||||||
|
mySQLColumnGroup: ''
|
||||||
|
# -1 means disabled. If you want that only activated players
|
||||||
|
# can log into your server, you can set here the group number
|
||||||
|
# of unactivated users, needed for some forum/CMS support
|
||||||
|
nonActivedUserGroup: -1
|
||||||
|
# Other MySQL columns where we need to put the username (case-sensitive)
|
||||||
|
mySQLOtherUsernameColumns: []
|
||||||
|
# How much log2 rounds needed in BCrypt (do not change if you do not know what it does)
|
||||||
|
bCryptLog2Round: 10
|
||||||
|
# phpBB table prefix defined during the phpBB installation process
|
||||||
|
phpbbTablePrefix: 'phpbb_'
|
||||||
|
# phpBB activated group ID; 2 is the default registered group defined by phpBB
|
||||||
|
phpbbActivatedGroupId: 2
|
||||||
|
# Wordpress prefix defined during WordPress installation
|
||||||
|
wordpressTablePrefix: 'wp_'
|
||||||
|
Converter:
|
||||||
|
Rakamak:
|
||||||
|
# Rakamak file name
|
||||||
|
fileName: 'users.rak'
|
||||||
|
# Rakamak use IP?
|
||||||
|
useIP: false
|
||||||
|
# Rakamak IP file name
|
||||||
|
ipFileName: 'UsersIp.rak'
|
||||||
|
CrazyLogin:
|
||||||
|
# CrazyLogin database file name
|
||||||
|
fileName: 'accounts.db'
|
||||||
|
settings:
|
||||||
|
sessions:
|
||||||
|
# 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.
|
||||||
|
enabled: false
|
||||||
|
# After how many minutes should a session expire?
|
||||||
|
# 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
|
||||||
|
timeout: 10
|
||||||
|
# Should the session expire if the player tries to log in with
|
||||||
|
# another IP address?
|
||||||
|
sessionExpireOnIpChange: true
|
||||||
|
# Message language, available languages:
|
||||||
|
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md
|
||||||
|
messagesLanguage: 'en'
|
||||||
|
restrictions:
|
||||||
|
# Keeps collisions disabled for logged players
|
||||||
|
# Works only with MC 1.9
|
||||||
|
keepCollisionsDisabled: false
|
||||||
|
# Can not authenticated players chat?
|
||||||
|
# Keep in mind that this feature also blocks all commands not
|
||||||
|
# listed in the list below.
|
||||||
|
allowChat: false
|
||||||
|
# Hide the chat log from players who are not authenticated?
|
||||||
|
hideChat: false
|
||||||
|
# Allowed commands for unauthenticated players
|
||||||
|
allowCommands:
|
||||||
|
- '/login'
|
||||||
|
- '/register'
|
||||||
|
- '/l'
|
||||||
|
- '/reg'
|
||||||
|
- '/email'
|
||||||
|
- '/captcha'
|
||||||
|
# Max number of allowed registrations per IP
|
||||||
|
# The value 0 means an unlimited number of registrations!
|
||||||
|
maxRegPerIp: 1
|
||||||
|
# Minimum allowed username length
|
||||||
|
minNicknameLength: 3
|
||||||
|
# Maximum allowed username length
|
||||||
|
maxNicknameLength: 16
|
||||||
|
# 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.
|
||||||
|
ForceSingleSession: true
|
||||||
|
ForceSpawnLocOnJoin:
|
||||||
|
# If enabled, every player that spawn in one of the world listed in
|
||||||
|
# "ForceSpawnLocOnJoin.worlds" will be teleported to the spawnpoint after successful
|
||||||
|
# authentication. The quit location of the player will be overwritten.
|
||||||
|
# This is different from "teleportUnAuthedToSpawn" that teleport player
|
||||||
|
# to the spawnpoint on join.
|
||||||
|
enabled: false
|
||||||
|
# WorldNames where we need to force the spawn location
|
||||||
|
# Case-sensitive!
|
||||||
|
worlds:
|
||||||
|
- 'world'
|
||||||
|
- 'world_nether'
|
||||||
|
- 'world_the_end'
|
||||||
|
# This option will save the quit location of the players.
|
||||||
|
SaveQuitLocation: false
|
||||||
|
# To activate the restricted user feature you need
|
||||||
|
# to enable this option and configure the AllowedRestrictedUser field.
|
||||||
|
AllowRestrictedUser: false
|
||||||
|
# The restricted user feature will kick players listed below
|
||||||
|
# if they don't match the defined IP address. Names are case-insensitive.
|
||||||
|
# Example:
|
||||||
|
# AllowedRestrictedUser:
|
||||||
|
# - playername;127.0.0.1
|
||||||
|
AllowedRestrictedUser: []
|
||||||
|
# Should unregistered players be kicked immediately?
|
||||||
|
kickNonRegistered: false
|
||||||
|
# Should players be kicked on wrong password?
|
||||||
|
kickOnWrongPassword: false
|
||||||
|
# Should not logged in players be teleported to the spawn?
|
||||||
|
# After the authentication they will be teleported back to
|
||||||
|
# their normal position.
|
||||||
|
teleportUnAuthedToSpawn: false
|
||||||
|
# Can unregistered players walk around?
|
||||||
|
allowMovement: false
|
||||||
|
# Should not authenticated players have speed = 0?
|
||||||
|
# This will reset the fly/walk speed to default value after the login.
|
||||||
|
removeSpeed: true
|
||||||
|
# After how many seconds should players who fail to login or register
|
||||||
|
# be kicked? Set to 0 to disable.
|
||||||
|
timeout: 30
|
||||||
|
# Regex syntax of allowed characters in the player name.
|
||||||
|
allowedNicknameCharacters: '[a-zA-Z0-9_]*'
|
||||||
|
# How far can unregistered players walk?
|
||||||
|
# Set to 0 for unlimited radius
|
||||||
|
allowedMovementRadius: 100
|
||||||
|
# Enable double check of password when you register
|
||||||
|
# when it's true, registration requires that kind of command:
|
||||||
|
# /register <password> <confirmPassword>
|
||||||
|
enablePasswordConfirmation: true
|
||||||
|
# Should we protect the player inventory before logging in? Requires ProtocolLib.
|
||||||
|
ProtectInventoryBeforeLogIn: true
|
||||||
|
# Should we deny the tabcomplete feature before logging in? Requires ProtocolLib.
|
||||||
|
DenyTabCompleteBeforeLogin: true
|
||||||
|
# Should we display all other accounts from a player when he joins?
|
||||||
|
# permission: /authme.admin.accounts
|
||||||
|
displayOtherAccounts: true
|
||||||
|
# Ban ip when the ip is not the ip registered in database
|
||||||
|
banUnsafedIP: false
|
||||||
|
# Spawn priority; values: authme, essentials, multiverse, default
|
||||||
|
spawnPriority: 'authme,essentials,multiverse,default'
|
||||||
|
# Maximum Login authorized by IP
|
||||||
|
maxLoginPerIp: 0
|
||||||
|
# Maximum Join authorized by IP
|
||||||
|
maxJoinPerIp: 0
|
||||||
|
# AuthMe will NEVER teleport players if set to true!
|
||||||
|
noTeleport: false
|
||||||
|
# Regex syntax for allowed chars in passwords
|
||||||
|
allowedPasswordCharacters: '[\x21-\x7E]*'
|
||||||
|
# Threshold of the other accounts command, a value less than 2 means disabled.
|
||||||
|
otherAccountsCmdThreshold: 0
|
||||||
|
# Command to run when a user has more accounts than the configured threshold.
|
||||||
|
# Available variables: %playername%, %playerip%
|
||||||
|
otherAccountsCmd: 'say The player %playername% with ip %playerip% has multiple accounts!'
|
||||||
|
# Log level: INFO, FINE, DEBUG. Use INFO for general messages,
|
||||||
|
# FINE for some additional detailed ones (like password failed),
|
||||||
|
# and DEBUG for debugging
|
||||||
|
logLevel: 'FINE'
|
||||||
|
# By default we schedule async tasks when talking to the database. If you want
|
||||||
|
# typical communication with the database to happen synchronously, set this to false
|
||||||
|
useAsyncTasks: true
|
||||||
|
GameMode:
|
||||||
|
# Force survival gamemode when player joins?
|
||||||
|
ForceSurvivalMode: false
|
||||||
|
unrestrictions:
|
||||||
|
# Below you can list all account names that AuthMe will ignore
|
||||||
|
# for registration or login. Configure it at your own risk!!
|
||||||
|
# This option adds compatibility with BuildCraft and some other mods.
|
||||||
|
# It is case-insensitive! Example:
|
||||||
|
# UnrestrictedName:
|
||||||
|
# - 'npcPlayer'
|
||||||
|
# - 'npcPlayer2'
|
||||||
|
UnrestrictedName: []
|
||||||
|
security:
|
||||||
|
# Minimum length of password
|
||||||
|
minPasswordLength: 5
|
||||||
|
# Maximum length of password
|
||||||
|
passwordMaxLength: 30
|
||||||
|
# This is a very important option: every time a player joins the server,
|
||||||
|
# if they are registered, AuthMe will switch him to unLoggedInGroup.
|
||||||
|
# This should prevent all major exploits.
|
||||||
|
# You can set up your permission plugin with this special group to have no permissions,
|
||||||
|
# or only permission to chat (or permission to send private messages etc.).
|
||||||
|
# The better way is to set up this group with few permissions, so if a player
|
||||||
|
# tries to exploit an account they can do only what you've defined for the group.
|
||||||
|
# After, a logged in player will be moved to his correct permissions group!
|
||||||
|
# Please note that the group name is case-sensitive, so 'admin' is different from 'Admin'
|
||||||
|
# Otherwise your group will be wiped and the player will join in the default group []!
|
||||||
|
# Example unLoggedinGroup: NotLogged
|
||||||
|
unLoggedinGroup: 'unLoggedinGroup'
|
||||||
|
# Possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB,
|
||||||
|
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
|
||||||
|
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only)
|
||||||
|
passwordHash: 'SHA256'
|
||||||
|
# Salt length for the SALTED2MD5 MD5(MD5(password)+salt)
|
||||||
|
doubleMD5SaltLength: 8
|
||||||
|
# If a password check fails, AuthMe will also try to check with the following hash methods.
|
||||||
|
# Use this setting when you change from one hash method to another.
|
||||||
|
# AuthMe will update the password to the new hash. Example:
|
||||||
|
# legacyHashes:
|
||||||
|
# - 'SHA1'
|
||||||
|
legacyHashes: []
|
||||||
|
# Prevent unsafe passwords from being used; put them in lowercase!
|
||||||
|
# You should always set 'help' as unsafePassword due to possible conflicts.
|
||||||
|
# unsafePasswords:
|
||||||
|
# - '123456'
|
||||||
|
# - 'password'
|
||||||
|
# - 'help'
|
||||||
|
unsafePasswords:
|
||||||
|
- '123456'
|
||||||
|
- 'password'
|
||||||
|
- 'qwerty'
|
||||||
|
- '12345'
|
||||||
|
- '54321'
|
||||||
|
- '123456789'
|
||||||
|
- 'help'
|
||||||
|
registration:
|
||||||
|
# Enable registration on the server?
|
||||||
|
enabled: true
|
||||||
|
# Send every X seconds a message to a player to
|
||||||
|
# remind him that he has to login/register
|
||||||
|
messageInterval: 5
|
||||||
|
# Only registered and logged in players can play.
|
||||||
|
# See restrictions for exceptions
|
||||||
|
force: true
|
||||||
|
# Do we replace password registration by an email registration method?
|
||||||
|
enableEmailRegistrationSystem: false
|
||||||
|
# Enable double check of email when you register
|
||||||
|
# when it's true, registration requires that kind of command:
|
||||||
|
# /register <email> <confirmEmail>
|
||||||
|
doubleEmailCheck: false
|
||||||
|
# Do we force kick a player after a successful registration?
|
||||||
|
# Do not use with login feature below
|
||||||
|
forceKickAfterRegister: false
|
||||||
|
# Does AuthMe need to enforce a /login after a successful registration?
|
||||||
|
forceLoginAfterRegister: false
|
||||||
|
# Force these commands after /login, without any '/', use %p to replace with player name
|
||||||
|
forceCommands: []
|
||||||
|
# Force these commands after /login as service console, without any '/'.
|
||||||
|
# Use %p to replace with player name
|
||||||
|
forceCommandsAsConsole: []
|
||||||
|
# Force these commands after /register, without any '/', use %p to replace with player name
|
||||||
|
forceRegisterCommands: []
|
||||||
|
# Force these commands after /register as a server console, without any '/'.
|
||||||
|
# Use %p to replace with player name
|
||||||
|
forceRegisterCommandsAsConsole: []
|
||||||
|
# Enable to display the welcome message (welcome.txt) after a login
|
||||||
|
# You can use colors in this welcome.txt + some replaced strings:
|
||||||
|
# {PLAYER}: player name, {ONLINE}: display number of online players,
|
||||||
|
# {MAXPLAYERS}: display server slots, {IP}: player ip, {LOGINS}: number of players logged,
|
||||||
|
# {WORLD}: player current world, {SERVER}: server name
|
||||||
|
# {VERSION}: get current bukkit version, {COUNTRY}: player country
|
||||||
|
useWelcomeMessage: true
|
||||||
|
# Broadcast the welcome message to the server or only to the player?
|
||||||
|
# set true for server or false for player
|
||||||
|
broadcastWelcomeMessage: false
|
||||||
|
# Should we delay the join message and display it once the player has logged in?
|
||||||
|
delayJoinMessage: false
|
||||||
|
# Should we remove the leave messages of unlogged users?
|
||||||
|
removeUnloggedLeaveMessage: false
|
||||||
|
# Should we remove join messages altogether?
|
||||||
|
removeJoinMessage: false
|
||||||
|
# Should we remove leave messages altogether?
|
||||||
|
removeLeaveMessage: false
|
||||||
|
# Do we need to add potion effect Blinding before login/reigster?
|
||||||
|
applyBlindEffect: false
|
||||||
|
# Do we need to prevent people to login with another case?
|
||||||
|
# If Xephi is registered, then Xephi can login, but not XEPHI/xephi/XePhI
|
||||||
|
preventOtherCase: false
|
||||||
|
permission:
|
||||||
|
# Take care with this option; if you want
|
||||||
|
# to use group switching of AuthMe
|
||||||
|
# for unloggedIn players, set this setting to true.
|
||||||
|
# Default is false.
|
||||||
|
EnablePermissionCheck: false
|
||||||
|
Email:
|
||||||
|
# Email SMTP server host
|
||||||
|
mailSMTP: 'smtp.gmail.com'
|
||||||
|
# Email SMTP server port
|
||||||
|
mailPort: 465
|
||||||
|
# Email account which sends the mails
|
||||||
|
mailAccount: ''
|
||||||
|
# Email account password
|
||||||
|
mailPassword: ''
|
||||||
|
# Custom sender name, replacing the mailAccount name in the email
|
||||||
|
mailSenderName: ''
|
||||||
|
# Recovery password length
|
||||||
|
RecoveryPasswordLength: 8
|
||||||
|
# Mail Subject
|
||||||
|
mailSubject: 'Your new AuthMe password'
|
||||||
|
# Like maxRegPerIP but with email
|
||||||
|
maxRegPerEmail: 1
|
||||||
|
# Recall players to add an email?
|
||||||
|
recallPlayers: false
|
||||||
|
# Delay in minute for the recall scheduler
|
||||||
|
delayRecall: 5
|
||||||
|
# Blacklist these domains for emails
|
||||||
|
emailBlacklisted:
|
||||||
|
- '10minutemail.com'
|
||||||
|
# Whitelist ONLY these domains for emails
|
||||||
|
emailWhitelisted: []
|
||||||
|
# Send the new password drawn in an image?
|
||||||
|
generateImage: false
|
||||||
|
# The OAuth2 token
|
||||||
|
emailOauth2Token: ''
|
||||||
|
Hooks:
|
||||||
|
# Do we need to hook with multiverse for spawn checking?
|
||||||
|
multiverse: true
|
||||||
|
# Do we need to hook with BungeeCord?
|
||||||
|
bungeecord: false
|
||||||
|
# Send player to this BungeeCord server after register/login
|
||||||
|
sendPlayerTo: ''
|
||||||
|
# Do we need to disable Essentials SocialSpy on join?
|
||||||
|
disableSocialSpy: true
|
||||||
|
# Do we need to force /motd Essentials command on join?
|
||||||
|
useEssentialsMotd: false
|
||||||
|
GroupOptions:
|
||||||
|
# Unregistered permission group
|
||||||
|
UnregisteredPlayerGroup: ''
|
||||||
|
# Registered permission group
|
||||||
|
RegisteredPlayerGroup: ''
|
||||||
|
Protection:
|
||||||
|
# Enable some servers protection (country based login, antibot)
|
||||||
|
enableProtection: false
|
||||||
|
# Apply the protection also to registered usernames
|
||||||
|
enableProtectionRegistered: true
|
||||||
|
# Countries allowed to join the server and register. For country codes, see
|
||||||
|
# http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/
|
||||||
|
# PLEASE USE QUOTES!
|
||||||
|
countries:
|
||||||
|
- 'US'
|
||||||
|
- 'GB'
|
||||||
|
# Countries not allowed to join the server and register
|
||||||
|
# PLEASE USE QUOTES!
|
||||||
|
countriesBlacklist:
|
||||||
|
- 'A1'
|
||||||
|
# Do we need to enable automatic antibot system?
|
||||||
|
enableAntiBot: true
|
||||||
|
# The interval in seconds
|
||||||
|
antiBotInterval: 5
|
||||||
|
# Max number of players allowed to login in the interval
|
||||||
|
# before the AntiBot system is enabled automatically
|
||||||
|
antiBotSensibility: 10
|
||||||
|
# Duration in minutes of the antibot automatic system
|
||||||
|
antiBotDuration: 10
|
||||||
|
# Delay in seconds before the antibot activation
|
||||||
|
antiBotDelay: 60
|
||||||
|
Purge:
|
||||||
|
# If enabled, AuthMe automatically purges old, unused accounts
|
||||||
|
useAutoPurge: false
|
||||||
|
# Number of days after which an account should be purged
|
||||||
|
daysBeforeRemovePlayer: 60
|
||||||
|
# Do we need to remove the player.dat file during purge process?
|
||||||
|
removePlayerDat: false
|
||||||
|
# Do we need to remove the Essentials/userdata/player.yml file during purge process?
|
||||||
|
removeEssentialsFile: false
|
||||||
|
# World where are players.dat stores
|
||||||
|
defaultWorld: 'world'
|
||||||
|
# Remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge?
|
||||||
|
removeLimitedCreativesInventories: false
|
||||||
|
# Do we need to remove the AntiXRayData/PlayerData/player file during purge process?
|
||||||
|
removeAntiXRayFile: false
|
||||||
|
# Do we need to remove permissions?
|
||||||
|
removePermissions: false
|
||||||
|
Security:
|
||||||
|
SQLProblem:
|
||||||
|
# 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!
|
||||||
|
stopServer: true
|
||||||
|
console:
|
||||||
|
# Remove passwords from console?
|
||||||
|
removePassword: true
|
||||||
|
# Copy AuthMe log output in a separate file as well?
|
||||||
|
logConsole: true
|
||||||
|
captcha:
|
||||||
|
# Enable captcha when a player uses wrong password too many times
|
||||||
|
useCaptcha: false
|
||||||
|
# Max allowed tries before a captcha is required
|
||||||
|
maxLoginTry: 5
|
||||||
|
# Captcha length
|
||||||
|
captchaLength: 5
|
||||||
|
tempban:
|
||||||
|
# Tempban a user's IP address if they enter the wrong password too many times
|
||||||
|
enableTempban: false
|
||||||
|
# How many times a user can attempt to login before their IP being tempbanned
|
||||||
|
maxLoginTries: 10
|
||||||
|
# The length of time a IP address will be tempbanned in minutes
|
||||||
|
# Default: 480 minutes, or 8 hours
|
||||||
|
tempbanLength: 480
|
||||||
|
# How many minutes before resetting the count for failed logins by IP and username
|
||||||
|
# Default: 480 minutes (8 hours)
|
||||||
|
minutesBeforeCounterReset: 480
|
||||||
|
recoveryCode:
|
||||||
|
# Number of characters a recovery code should have (0 to disable)
|
||||||
|
length: 8
|
||||||
|
# How many hours is a recovery code valid for?
|
||||||
|
validForHours: 4
|
||||||
|
BackupSystem:
|
||||||
|
# Enable or disable automatic backup
|
||||||
|
ActivateBackup: false
|
||||||
|
# Set backup at every start of server
|
||||||
|
OnServerStart: false
|
||||||
|
# Set backup at every stop of server
|
||||||
|
OnServerStop: true
|
||||||
|
# Windows only mysql installation Path
|
||||||
|
MysqlWindowsPath: 'C:\Program Files\MySQL\MySQL Server 5.1\'
|
||||||
|
```
|
||||||
|
|
||||||
|
To change settings on a running server, save your changes to config.yml and use
|
||||||
|
`/authme reload`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Nov 13 13:34:49 CET 2016
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sat Oct 01 23:42:20 CEST 2016. See hashmethods/hash_algorithms.tpl.md -->
|
<!-- File auto-generated on Fri Nov 25 15:48:35 CET 2016. See docs/hashmethods/hash_algorithms.tpl.md -->
|
||||||
|
|
||||||
## Hash Algorithms
|
## Hash Algorithms
|
||||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||||
@ -13,11 +13,11 @@ CRAZYCRYPT1 | Do not use | 128 | | | Username | |
|
|||||||
DOUBLEMD5 | Do not use | 32 | | | None | |
|
DOUBLEMD5 | Do not use | 32 | | | None | |
|
||||||
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
||||||
IPB4 | Does not work | 60 | | | Text | 22 | Y
|
IPB4 | Does not work | 60 | | | Text | 22 | Y
|
||||||
JOOMLA | Recommended | 65 | | | Text | 32 |
|
JOOMLA | Acceptable | 65 | | | Text | 32 |
|
||||||
MD5 | Do not use | 32 | | | None | |
|
MD5 | Do not use | 32 | | | None | |
|
||||||
MD5VB | Acceptable | 56 | | | Text | 16 |
|
MD5VB | Acceptable | 56 | | | Text | 16 |
|
||||||
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
||||||
PBKDF2 | Does not work | 332 | | | Text | 12 |
|
PBKDF2 | Recommended | 165 | | | Text | 16 |
|
||||||
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
|
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
|
||||||
PHPBB | Acceptable | 34 | | | Text | 16 |
|
PHPBB | Acceptable | 34 | | | Text | 16 |
|
||||||
PHPFUSION | Do not use | 64 | Y | | | | Y
|
PHPFUSION | Do not use | 64 | Y | | | | Y
|
||||||
@ -82,4 +82,4 @@ or bad.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 01 23:42:20 CEST 2016
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Nov 25 15:48:35 CET 2016
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sun Oct 16 21:39:10 CEST 2016. See permissions/permission_nodes.tpl.md -->
|
<!-- File auto-generated on Sun Oct 23 15:38:58 CEST 2016. See permissions/permission_nodes.tpl.md -->
|
||||||
|
|
||||||
## AuthMe Permission Nodes
|
## AuthMe Permission Nodes
|
||||||
The following are the permission nodes that are currently supported by the latest dev builds.
|
The following are the permission nodes that are currently supported by the latest dev builds.
|
||||||
@ -38,15 +38,15 @@ The following are the permission nodes that are currently supported by the lates
|
|||||||
- **authme.player.email** – Grants all email permissions.
|
- **authme.player.email** – Grants all email permissions.
|
||||||
- **authme.player.email.add** – Command permission to add an email address.
|
- **authme.player.email.add** – Command permission to add an email address.
|
||||||
- **authme.player.email.change** – Command permission to change the email address.
|
- **authme.player.email.change** – Command permission to change the email address.
|
||||||
- **authme.player.email.recover** – Command permission to recover an account using it's email address.
|
- **authme.player.email.recover** – Command permission to recover an account using its email address.
|
||||||
- **authme.player.login** – Command permission to login.
|
- **authme.player.login** – Command permission to login.
|
||||||
- **authme.player.logout** – Command permission to logout.
|
- **authme.player.logout** – Command permission to logout.
|
||||||
- **authme.player.register** – Command permission to register.
|
- **authme.player.register** – Command permission to register.
|
||||||
- **authme.player.seeownaccounts** – Permission to use to see own other accounts.
|
- **authme.player.seeownaccounts** – Permission to use to see own other accounts.
|
||||||
- **authme.player.unregister** – Command permission to unregister.
|
- **authme.player.unregister** – Command permission to unregister.
|
||||||
- **authme.vip** – Permission node to identify VIP users.
|
- **authme.vip** – When the server is full and someone with this permission joins the server, someone will be kicked.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 16 21:39:10 CEST 2016
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 23 15:38:58 CEST 2016
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sun Oct 09 09:42:48 CEST 2016. See translations/translations.tpl.md -->
|
<!-- File auto-generated on Sun Dec 11 08:16:38 CET 2016. See docs/translations/translations.tpl.md -->
|
||||||
|
|
||||||
# AuthMe Translations
|
# AuthMe Translations
|
||||||
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
||||||
@ -8,32 +8,34 @@ in your config.yml to use the language, or use another language code to start a
|
|||||||
Code | Language | Translated |
|
Code | Language | Translated |
|
||||||
---- | -------- | ---------: | ------
|
---- | -------- | ---------: | ------
|
||||||
[en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 73% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=73&h=5&txtpad=1" alt="bar" />
|
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 71% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=71&h=5&txtpad=1" alt="bar" />
|
||||||
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 91% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=91&h=5&txtpad=1" alt="bar" />
|
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 88% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=88&h=5&txtpad=1" alt="bar" />
|
||||||
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 97% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ee55&w=97&h=5&txtpad=1" alt="bar" />
|
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
||||||
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 66% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=66&h=5&txtpad=1" alt="bar" />
|
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 64% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=64&h=5&txtpad=1" alt="bar" />
|
||||||
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 70% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=70&h=5&txtpad=1" alt="bar" />
|
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 68% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=68&h=5&txtpad=1" alt="bar" />
|
||||||
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 97% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ee55&w=97&h=5&txtpad=1" alt="bar" />
|
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
||||||
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 74% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=74&h=5&txtpad=1" alt="bar" />
|
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 72% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=72&h=5&txtpad=1" alt="bar" />
|
||||||
[hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 74% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=74&h=5&txtpad=1" alt="bar" />
|
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 72% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=72&h=5&txtpad=1" alt="bar" />
|
||||||
[it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 76% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=76&h=5&txtpad=1" alt="bar" />
|
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 74% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=74&h=5&txtpad=1" alt="bar" />
|
||||||
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Latvian | 57% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=57&h=5&txtpad=1" alt="bar" />
|
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Latvian | 55% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=55&h=5&txtpad=1" alt="bar" />
|
||||||
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 80% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=80&h=5&txtpad=1" alt="bar" />
|
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 78% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=78&h=5&txtpad=1" alt="bar" />
|
||||||
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 91% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=91&h=5&txtpad=1" alt="bar" />
|
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 88% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=88&h=5&txtpad=1" alt="bar" />
|
||||||
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 97% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ee55&w=97&h=5&txtpad=1" alt="bar" />
|
[ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 50% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=50&h=5&txtpad=1" alt="bar" />
|
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
||||||
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 49% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=49&h=5&txtpad=1" alt="bar" />
|
||||||
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 97% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ee55&w=97&h=5&txtpad=1" alt="bar" />
|
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 83% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=83&h=5&txtpad=1" alt="bar" />
|
||||||
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
||||||
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 83% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=83&h=5&txtpad=1" alt="bar" />
|
||||||
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 83% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=83&h=5&txtpad=1" alt="bar" />
|
||||||
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 83% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=83&h=5&txtpad=1" alt="bar" />
|
||||||
|
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 83% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=83&h=5&txtpad=1" alt="bar" />
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 09 09:42:48 CEST 2016
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Dec 11 08:16:38 CET 2016
|
||||||
|
|||||||
27
pom.xml
27
pom.xml
@ -62,7 +62,7 @@
|
|||||||
<bukkitplugin.authors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu, Gnat008</bukkitplugin.authors>
|
<bukkitplugin.authors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu, Gnat008</bukkitplugin.authors>
|
||||||
|
|
||||||
<!-- Change Bukkit Version HERE! -->
|
<!-- Change Bukkit Version HERE! -->
|
||||||
<bukkit.version>1.10.2-R0.1-SNAPSHOT</bukkit.version>
|
<bukkit.version>1.11-R0.1-SNAPSHOT</bukkit.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- Jenkins profile -->
|
<!-- Jenkins profile -->
|
||||||
@ -196,7 +196,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.6.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>${project.jdkVersion}</source>
|
<source>${project.jdkVersion}</source>
|
||||||
<target>${project.jdkVersion}</target>
|
<target>${project.jdkVersion}</target>
|
||||||
@ -268,6 +268,10 @@
|
|||||||
<pattern>net.ricecode.similarity</pattern>
|
<pattern>net.ricecode.similarity</pattern>
|
||||||
<shadedPattern>fr.xephi.authme.libs.ricecode.similarity</shadedPattern>
|
<shadedPattern>fr.xephi.authme.libs.ricecode.similarity</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>de.rtner</pattern>
|
||||||
|
<shadedPattern>fr.xephi.authme.libs.de.rtner</shadedPattern>
|
||||||
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>javax.inject</pattern>
|
<pattern>javax.inject</pattern>
|
||||||
<shadedPattern>fr.xephi.authme.libs.javax.inject</shadedPattern>
|
<shadedPattern>fr.xephi.authme.libs.javax.inject</shadedPattern>
|
||||||
@ -319,6 +323,10 @@
|
|||||||
<pattern>net.ricecode.similarity</pattern>
|
<pattern>net.ricecode.similarity</pattern>
|
||||||
<shadedPattern>fr.xephi.authme.libs.ricecode.similarity</shadedPattern>
|
<shadedPattern>fr.xephi.authme.libs.ricecode.similarity</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>de.rtner</pattern>
|
||||||
|
<shadedPattern>fr.xephi.authme.libs.de.rtner</shadedPattern>
|
||||||
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>javax.inject</pattern>
|
<pattern>javax.inject</pattern>
|
||||||
<shadedPattern>fr.xephi.authme.libs.javax.inject</shadedPattern>
|
<shadedPattern>fr.xephi.authme.libs.javax.inject</shadedPattern>
|
||||||
@ -524,6 +532,13 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- PBKDF2 implementation -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.rtner</groupId>
|
||||||
|
<artifactId>PBKDF2</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spigot API, http://www.spigotmc.org/ or http://bukkit.org/ -->
|
<!-- Spigot API, http://www.spigotmc.org/ or http://bukkit.org/ -->
|
||||||
<!-- Moved in profiles! -->
|
<!-- Moved in profiles! -->
|
||||||
|
|
||||||
@ -873,7 +888,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.authme</groupId>
|
<groupId>com.github.authme</groupId>
|
||||||
<artifactId>configme</artifactId>
|
<artifactId>configme</artifactId>
|
||||||
<version>0.2</version>
|
<version>0.2.1</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
@ -904,7 +919,7 @@
|
|||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<version>2.0.5-beta</version>
|
<version>2.2.27</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>hamcrest-core</artifactId>
|
<artifactId>hamcrest-core</artifactId>
|
||||||
@ -917,13 +932,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<version>3.8.11.2</version>
|
<version>3.15.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.4.192</version>
|
<version>1.4.193</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@ -109,7 +109,6 @@ abstract class AuthMeController {
|
|||||||
* @return string|null the hash, or null if unavailable (e.g. username doesn't exist)
|
* @return string|null the hash, or null if unavailable (e.g. username doesn't exist)
|
||||||
*/
|
*/
|
||||||
private function getHashFromDatabase($username) {
|
private function getHashFromDatabase($username) {
|
||||||
// Add here your database host, username, password and database name
|
|
||||||
$mysqli = $this->getAuthmeMySqli();
|
$mysqli = $this->getAuthmeMySqli();
|
||||||
if ($mysqli !== null) {
|
if ($mysqli !== null) {
|
||||||
$stmt = $mysqli->prepare('SELECT password FROM ' . self::AUTHME_TABLE . ' WHERE username = ?');
|
$stmt = $mysqli->prepare('SELECT password FROM ' . self::AUTHME_TABLE . ' WHERE username = ?');
|
||||||
|
|||||||
53
samples/website_integration/Pbkdf2.php
Normal file
53
samples/website_integration/Pbkdf2.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* AuthMe website integration logic for PBKDF2 *
|
||||||
|
* ------------------------------------------------------- *
|
||||||
|
* See AuthMeController for details. *
|
||||||
|
* *
|
||||||
|
* Source: https://github.com/AuthMe-Team/AuthMeReloaded/ *
|
||||||
|
***********************************************************/
|
||||||
|
class Pbkdf2 extends AuthMeController {
|
||||||
|
|
||||||
|
/** @var string[] range of characters for salt generation */
|
||||||
|
private $CHARS;
|
||||||
|
|
||||||
|
const SALT_LENGTH = 16;
|
||||||
|
const NUMBER_OF_ITERATIONS = 10000;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->CHARS = self::initCharRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isValidPassword($password, $hash) {
|
||||||
|
// hash := pbkdf2_sha256$iterations$salt$hash
|
||||||
|
$parts = explode('$', $hash);
|
||||||
|
return count($parts) === 4 && $hash === $this->computeHash($parts[1], $parts[2], $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hash($password) {
|
||||||
|
$salt = $this->generateSalt();
|
||||||
|
return $this->computeHash(self::NUMBER_OF_ITERATIONS, $salt, $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function computeHash($iterations, $salt, $password) {
|
||||||
|
return 'pbkdf2_sha256$' . self::NUMBER_OF_ITERATIONS . '$' . $salt
|
||||||
|
. '$' . hash_pbkdf2('sha256', $password, $salt, self::NUMBER_OF_ITERATIONS, 64, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string randomly generated salt
|
||||||
|
*/
|
||||||
|
private function generateSalt() {
|
||||||
|
$maxCharIndex = count($this->CHARS) - 1;
|
||||||
|
$salt = '';
|
||||||
|
for ($i = 0; $i < self::SALT_LENGTH; ++$i) {
|
||||||
|
$salt .= $this->CHARS[mt_rand(0, $maxCharIndex)];
|
||||||
|
}
|
||||||
|
return $salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function initCharRange() {
|
||||||
|
return array_merge(range('0', '9'), range('a', 'f'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ class Sha256 extends AuthMeController {
|
|||||||
const SALT_LENGTH = 16;
|
const SALT_LENGTH = 16;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->CHARS = self::initRandomChars();
|
$this->CHARS = self::initCharRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isValidPassword($password, $hash) {
|
protected function isValidPassword($password, $hash) {
|
||||||
@ -41,7 +41,7 @@ class Sha256 extends AuthMeController {
|
|||||||
return $salt;
|
return $salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function initRandomChars() {
|
private static function initCharRange() {
|
||||||
return array_merge(range('0', '9'), range('a', 'f'));
|
return array_merge(range('0', '9'), range('a', 'f'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,44 +5,45 @@ import ch.jalu.injector.InjectorBuilder;
|
|||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import fr.xephi.authme.api.API;
|
import fr.xephi.authme.api.API;
|
||||||
import fr.xephi.authme.api.NewAPI;
|
import fr.xephi.authme.api.NewAPI;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
|
||||||
import fr.xephi.authme.command.CommandHandler;
|
import fr.xephi.authme.command.CommandHandler;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.initialization.DataFolder;
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
import fr.xephi.authme.initialization.Initializer;
|
import fr.xephi.authme.initialization.DataSourceProvider;
|
||||||
import fr.xephi.authme.initialization.MetricsManager;
|
|
||||||
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
|
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
|
||||||
|
import fr.xephi.authme.initialization.OnStartupTasks;
|
||||||
|
import fr.xephi.authme.initialization.SettingsProvider;
|
||||||
import fr.xephi.authme.initialization.TaskCloser;
|
import fr.xephi.authme.initialization.TaskCloser;
|
||||||
import fr.xephi.authme.listener.BlockListener;
|
import fr.xephi.authme.listener.BlockListener;
|
||||||
import fr.xephi.authme.listener.EntityListener;
|
import fr.xephi.authme.listener.EntityListener;
|
||||||
import fr.xephi.authme.listener.PlayerListener;
|
import fr.xephi.authme.listener.PlayerListener;
|
||||||
|
import fr.xephi.authme.listener.PlayerListener111;
|
||||||
import fr.xephi.authme.listener.PlayerListener16;
|
import fr.xephi.authme.listener.PlayerListener16;
|
||||||
import fr.xephi.authme.listener.PlayerListener18;
|
import fr.xephi.authme.listener.PlayerListener18;
|
||||||
import fr.xephi.authme.listener.PlayerListener19;
|
import fr.xephi.authme.listener.PlayerListener19;
|
||||||
import fr.xephi.authme.listener.ServerListener;
|
import fr.xephi.authme.listener.ServerListener;
|
||||||
import fr.xephi.authme.message.Messages;
|
|
||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.permission.PermissionsSystemType;
|
import fr.xephi.authme.permission.PermissionsSystemType;
|
||||||
import fr.xephi.authme.security.crypts.SHA256;
|
import fr.xephi.authme.security.crypts.SHA256;
|
||||||
import fr.xephi.authme.service.BackupService;
|
import fr.xephi.authme.service.BackupService;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.service.GeoIpService;
|
import fr.xephi.authme.service.GeoIpService;
|
||||||
|
import fr.xephi.authme.service.MigrationService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import fr.xephi.authme.task.CleanupTask;
|
import fr.xephi.authme.task.CleanupTask;
|
||||||
import fr.xephi.authme.task.purge.PurgeService;
|
import fr.xephi.authme.task.purge.PurgeService;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
|
||||||
import fr.xephi.authme.service.MigrationService;
|
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.PluginLoader;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -60,7 +61,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
private static final String LOG_FILENAME = "authme.log";
|
private static final String LOG_FILENAME = "authme.log";
|
||||||
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
||||||
|
|
||||||
// Default version and build number values;
|
// Default version and build number values
|
||||||
private static String pluginVersion = "N/D";
|
private static String pluginVersion = "N/D";
|
||||||
private static String pluginBuildNumber = "Unknown";
|
private static String pluginBuildNumber = "Unknown";
|
||||||
|
|
||||||
@ -68,7 +69,6 @@ public class AuthMe extends JavaPlugin {
|
|||||||
private CommandHandler commandHandler;
|
private CommandHandler commandHandler;
|
||||||
private PermissionsManager permsMan;
|
private PermissionsManager permsMan;
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
private Messages messages;
|
|
||||||
private DataSource database;
|
private DataSource database;
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
private Injector injector;
|
private Injector injector;
|
||||||
@ -86,9 +86,8 @@ public class AuthMe extends JavaPlugin {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@SuppressWarnings("deprecation") // the super constructor is deprecated to mark it for unit testing only
|
@SuppressWarnings("deprecation") // the super constructor is deprecated to mark it for unit testing only
|
||||||
protected AuthMe(final PluginLoader loader, final Server server, final PluginDescriptionFile description,
|
protected AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||||
final File dataFolder, final File file) {
|
super(loader, description, dataFolder, file);
|
||||||
super(loader, server, description, dataFolder, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +132,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
// Load the plugin version data from the plugin description file
|
// Load the plugin version data from the plugin description file
|
||||||
loadPluginInfo();
|
loadPluginInfo(getDescription().getVersion());
|
||||||
|
|
||||||
// Initialize the plugin
|
// Initialize the plugin
|
||||||
try {
|
try {
|
||||||
@ -156,7 +155,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
new BackupService(this, settings).doBackup(BackupService.BackupCause.START);
|
new BackupService(this, settings).doBackup(BackupService.BackupCause.START);
|
||||||
|
|
||||||
// Set up Metrics
|
// Set up Metrics
|
||||||
MetricsManager.sendMetrics(this, settings);
|
OnStartupTasks.sendMetrics(this, settings);
|
||||||
|
|
||||||
// Sponsor messages
|
// Sponsor messages
|
||||||
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
|
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
|
||||||
@ -176,9 +175,10 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the version and build number of the plugin from the description file.
|
* Load the version and build number of the plugin from the description file.
|
||||||
|
*
|
||||||
|
* @param versionRaw the version as given by the plugin description file
|
||||||
*/
|
*/
|
||||||
private void loadPluginInfo() {
|
private static void loadPluginInfo(String versionRaw) {
|
||||||
String versionRaw = this.getDescription().getVersion();
|
|
||||||
int index = versionRaw.lastIndexOf("-");
|
int index = versionRaw.lastIndexOf("-");
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
pluginVersion = versionRaw.substring(0, index);
|
pluginVersion = versionRaw.substring(0, index);
|
||||||
@ -191,10 +191,8 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the plugin and all the services.
|
* Initialize the plugin and all the services.
|
||||||
*
|
|
||||||
* @throws Exception if the initialization fails
|
|
||||||
*/
|
*/
|
||||||
private void initialize() throws Exception {
|
private void initialize() {
|
||||||
// Set the Logger instance and log file path
|
// Set the Logger instance and log file path
|
||||||
ConsoleLogger.setLogger(getLogger());
|
ConsoleLogger.setLogger(getLogger());
|
||||||
ConsoleLogger.setLogFile(new File(getDataFolder(), LOG_FILENAME));
|
ConsoleLogger.setLogFile(new File(getDataFolder(), LOG_FILENAME));
|
||||||
@ -202,40 +200,30 @@ public class AuthMe extends JavaPlugin {
|
|||||||
// Create plugin folder
|
// Create plugin folder
|
||||||
getDataFolder().mkdir();
|
getDataFolder().mkdir();
|
||||||
|
|
||||||
// Load settings and set up the console and console filter
|
// Create injector, provide elements from the Bukkit environment and register providers
|
||||||
settings = Initializer.createSettings(this);
|
|
||||||
bukkitService = new BukkitService(this, settings);
|
|
||||||
Initializer initializer = new Initializer(this, bukkitService);
|
|
||||||
|
|
||||||
ConsoleLogger.setLoggingOptions(settings);
|
|
||||||
initializer.setupConsoleFilter(settings, getLogger());
|
|
||||||
|
|
||||||
// Connect to the database and set up tables
|
|
||||||
database = initializer.setupDatabase(settings);
|
|
||||||
|
|
||||||
// Convert deprecated PLAINTEXT hash entries
|
|
||||||
MigrationService.changePlainTextToSha256(settings, database, new SHA256());
|
|
||||||
|
|
||||||
// Injector initialization
|
|
||||||
injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create();
|
injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create();
|
||||||
|
|
||||||
// Register elements of the Bukkit / JavaPlugin environment
|
|
||||||
injector.register(AuthMe.class, this);
|
injector.register(AuthMe.class, this);
|
||||||
injector.register(Server.class, getServer());
|
injector.register(Server.class, getServer());
|
||||||
injector.register(PluginManager.class, getServer().getPluginManager());
|
injector.register(PluginManager.class, getServer().getPluginManager());
|
||||||
injector.register(BukkitScheduler.class, getServer().getScheduler());
|
injector.register(BukkitScheduler.class, getServer().getScheduler());
|
||||||
injector.provide(DataFolder.class, getDataFolder());
|
injector.provide(DataFolder.class, getDataFolder());
|
||||||
|
injector.registerProvider(Settings.class, SettingsProvider.class);
|
||||||
|
injector.registerProvider(DataSource.class, DataSourceProvider.class);
|
||||||
|
|
||||||
// Register elements we instantiate manually
|
// Get settings and set up logger
|
||||||
injector.register(Settings.class, settings);
|
settings = injector.getSingleton(Settings.class);
|
||||||
injector.register(DataSource.class, database);
|
ConsoleLogger.setLoggingOptions(settings);
|
||||||
injector.register(BukkitService.class, bukkitService);
|
OnStartupTasks.setupConsoleFilter(settings, getLogger());
|
||||||
|
|
||||||
|
// Set all service fields on the AuthMe class
|
||||||
instantiateServices(injector);
|
instantiateServices(injector);
|
||||||
|
|
||||||
|
// Convert deprecated PLAINTEXT hash entries
|
||||||
|
MigrationService.changePlainTextToSha256(settings, database, new SHA256());
|
||||||
|
|
||||||
// TODO: does this still make sense? -sgdc3
|
// TODO: does this still make sense? -sgdc3
|
||||||
// If the server is empty (fresh start) just set all the players as unlogged
|
// If the server is empty (fresh start) just set all the players as unlogged
|
||||||
if (bukkitService.getOnlinePlayers().size() == 0) {
|
if (bukkitService.getOnlinePlayers().isEmpty()) {
|
||||||
database.purgeLogged();
|
database.purgeLogged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +231,8 @@ public class AuthMe extends JavaPlugin {
|
|||||||
registerEventListeners(injector);
|
registerEventListeners(injector);
|
||||||
|
|
||||||
// Start Email recall task if needed
|
// Start Email recall task if needed
|
||||||
initializer.scheduleRecallEmailTask(settings, database, messages);
|
OnStartupTasks onStartupTasks = injector.newInstance(OnStartupTasks.class);
|
||||||
|
onStartupTasks.scheduleRecallEmailTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,7 +245,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
playerCache = PlayerCache.getInstance();
|
playerCache = PlayerCache.getInstance();
|
||||||
injector.register(PlayerCache.class, playerCache);
|
injector.register(PlayerCache.class, playerCache);
|
||||||
|
|
||||||
messages = injector.getSingleton(Messages.class);
|
database = injector.getSingleton(DataSource.class);
|
||||||
permsMan = injector.getSingleton(PermissionsManager.class);
|
permsMan = injector.getSingleton(PermissionsManager.class);
|
||||||
bukkitService = injector.getSingleton(BukkitService.class);
|
bukkitService = injector.getSingleton(BukkitService.class);
|
||||||
commandHandler = injector.getSingleton(CommandHandler.class);
|
commandHandler = injector.getSingleton(CommandHandler.class);
|
||||||
@ -312,6 +301,11 @@ public class AuthMe extends JavaPlugin {
|
|||||||
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register listener for 1.11 events if available
|
||||||
|
if (isClassLoaded("org.bukkit.event.entity.EntityAirChangeEvent")) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(PlayerListener111.class), this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -343,10 +337,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for tasks and close data source
|
// Wait for tasks and close data source
|
||||||
new Thread(
|
new TaskCloser(this, database).run();
|
||||||
new TaskCloser(this, database),
|
|
||||||
"AuthMe-DataSource#close"
|
|
||||||
).start();
|
|
||||||
|
|
||||||
// Disabled correctly
|
// Disabled correctly
|
||||||
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
|
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
|
||||||
|
|||||||
@ -19,12 +19,13 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated API of AuthMe. Please use {@link NewAPI} instead.
|
* Deprecated API of AuthMe. Please use {@link NewAPI} instead.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link NewAPI}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class API {
|
public class API {
|
||||||
|
|
||||||
public static final String newline = System.getProperty("line.separator");
|
private static AuthMe instance;
|
||||||
public static AuthMe instance;
|
|
||||||
private static DataSource dataSource;
|
private static DataSource dataSource;
|
||||||
private static PasswordSecurity passwordSecurity;
|
private static PasswordSecurity passwordSecurity;
|
||||||
private static Management management;
|
private static Management management;
|
||||||
@ -83,28 +84,17 @@ public class API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Location getLastLocation(Player player) {
|
public static Location getLastLocation(Player player) {
|
||||||
try {
|
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
||||||
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase());
|
|
||||||
|
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
|
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
|
||||||
return loc;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setPlayerInventory(Player player, ItemStack[] content,
|
public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) {
|
||||||
ItemStack[] armor) {
|
player.getInventory().setContents(content);
|
||||||
try {
|
player.getInventory().setArmorContents(armor);
|
||||||
player.getInventory().setContents(content);
|
|
||||||
player.getInventory().setArmorContents(armor);
|
|
||||||
} catch (NullPointerException ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -25,8 +25,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class NewAPI {
|
public class NewAPI {
|
||||||
|
|
||||||
public static NewAPI singleton;
|
private static NewAPI singleton;
|
||||||
public final AuthMe plugin;
|
private final AuthMe plugin;
|
||||||
private final PluginHookService pluginHookService;
|
private final PluginHookService pluginHookService;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final PasswordSecurity passwordSecurity;
|
private final PasswordSecurity passwordSecurity;
|
||||||
|
|||||||
@ -87,10 +87,10 @@ public class CommandMapper {
|
|||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List<String> parts) {
|
private static FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List<String> parts) {
|
||||||
// Return the base command with incorrect arg count error if we only have one part
|
// Return the base command with incorrect arg count error if we only have one part
|
||||||
if (parts.size() <= 1) {
|
if (parts.size() <= 1) {
|
||||||
return new FoundCommandResult(base, parts, new ArrayList<String>(), 0.0, INCORRECT_ARGUMENTS);
|
return new FoundCommandResult(base, parts, new ArrayList<>(), 0.0, INCORRECT_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String childLabel = parts.get(1);
|
final String childLabel = parts.get(1);
|
||||||
@ -115,7 +115,7 @@ public class CommandMapper {
|
|||||||
final int partsSize = parts.size();
|
final int partsSize = parts.size();
|
||||||
List<String> labels = parts.subList(0, Math.min(closestCommand.getLabelCount(), partsSize));
|
List<String> labels = parts.subList(0, Math.min(closestCommand.getLabelCount(), partsSize));
|
||||||
List<String> arguments = (labels.size() == partsSize)
|
List<String> arguments = (labels.size() == partsSize)
|
||||||
? new ArrayList<String>()
|
? new ArrayList<>()
|
||||||
: parts.subList(labels.size(), partsSize);
|
: parts.subList(labels.size(), partsSize);
|
||||||
|
|
||||||
return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status);
|
return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status);
|
||||||
@ -141,7 +141,7 @@ public class CommandMapper {
|
|||||||
*
|
*
|
||||||
* @return A command if there was a complete match (including proper argument count), null otherwise
|
* @return A command if there was a complete match (including proper argument count), null otherwise
|
||||||
*/
|
*/
|
||||||
private CommandDescription getSuitableChild(CommandDescription baseCommand, List<String> parts) {
|
private static CommandDescription getSuitableChild(CommandDescription baseCommand, List<String> parts) {
|
||||||
if (CollectionUtils.isEmpty(parts)) {
|
if (CollectionUtils.isEmpty(parts)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
package fr.xephi.authme.command;
|
|
||||||
|
|
||||||
import com.github.authme.configme.properties.Property;
|
|
||||||
import fr.xephi.authme.message.MessageKey;
|
|
||||||
import fr.xephi.authme.message.Messages;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.service.ValidationService;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
|
|
||||||
* This service basically wraps calls, forwarding them to other classes.
|
|
||||||
*/
|
|
||||||
public class CommandService {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private Messages messages;
|
|
||||||
@Inject
|
|
||||||
private Settings settings;
|
|
||||||
@Inject
|
|
||||||
private ValidationService validationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message to a player.
|
|
||||||
*
|
|
||||||
* @param sender The command sender to send the message to
|
|
||||||
* @param messageKey The message key to send
|
|
||||||
*/
|
|
||||||
public void send(CommandSender sender, MessageKey messageKey) {
|
|
||||||
messages.send(sender, messageKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message to a player.
|
|
||||||
*
|
|
||||||
* @param sender The command sender to send the message to
|
|
||||||
* @param messageKey The message key to send
|
|
||||||
* @param replacements The replacement arguments for the message key's tags
|
|
||||||
*/
|
|
||||||
public void send(CommandSender sender, MessageKey messageKey, String... replacements) {
|
|
||||||
messages.send(sender, messageKey, replacements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a message by its message key.
|
|
||||||
*
|
|
||||||
* @param key The message to retrieve
|
|
||||||
* @return The message
|
|
||||||
*/
|
|
||||||
public String[] retrieveMessage(MessageKey key) {
|
|
||||||
return messages.retrieve(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a message as a single String by its message key.
|
|
||||||
*
|
|
||||||
* @param key The message to retrieve
|
|
||||||
* @return The message
|
|
||||||
*/
|
|
||||||
public String retrieveSingle(MessageKey key) {
|
|
||||||
return messages.retrieveSingle(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the given property's value.
|
|
||||||
*
|
|
||||||
* @param property The property to retrieve
|
|
||||||
* @param <T> The type of the property
|
|
||||||
* @return The property's value
|
|
||||||
*/
|
|
||||||
public <T> T getProperty(Property<T> property) {
|
|
||||||
return settings.getProperty(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the settings manager.
|
|
||||||
*
|
|
||||||
* @return The settings manager
|
|
||||||
*/
|
|
||||||
public Settings getSettings() {
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateEmail(String email) {
|
|
||||||
return validationService.validateEmail(email);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
|
|
||||||
return validationService.isEmailFreeForRegistration(email, sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,11 +1,11 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -23,7 +23,7 @@ public class AccountsCommand implements ExecutableCommand {
|
|||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||||
@ -50,13 +50,13 @@ public class AccountsCommand implements ExecutableCommand {
|
|||||||
public void run() {
|
public void run() {
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase());
|
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase());
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> accountList = dataSource.getAllAuthsByIp(auth.getIp());
|
List<String> accountList = dataSource.getAllAuthsByIp(auth.getIp());
|
||||||
if (accountList.isEmpty()) {
|
if (accountList.isEmpty()) {
|
||||||
commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
commonService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||||
} else if (accountList.size() == 1) {
|
} else if (accountList.size() == 1) {
|
||||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -38,7 +38,7 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
|||||||
private ValidationService validationService;
|
private ValidationService validationService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||||
@ -49,38 +49,45 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
|||||||
// Validate the password
|
// Validate the password
|
||||||
ValidationResult validationResult = validationService.validatePassword(playerPass, playerName);
|
ValidationResult validationResult = validationService.validatePassword(playerPass, playerName);
|
||||||
if (validationResult.hasError()) {
|
if (validationResult.hasError()) {
|
||||||
commandService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
commonService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the password
|
// Set the password
|
||||||
final String playerNameLowerCase = playerName.toLowerCase();
|
bukkitService.runTaskOptionallyAsync(() -> changePassword(playerName.toLowerCase(), playerPass, sender));
|
||||||
bukkitService.runTaskOptionallyAsync(new Runnable() {
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void run() {
|
* Changes the password of the given player to the given password.
|
||||||
PlayerAuth auth = null;
|
*
|
||||||
if (playerCache.isAuthenticated(playerNameLowerCase)) {
|
* @param nameLowercase the name of the player
|
||||||
auth = playerCache.getAuth(playerNameLowerCase);
|
* @param password the password to set
|
||||||
} else if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
* @param sender the sender initiating the password change
|
||||||
auth = dataSource.getAuth(playerNameLowerCase);
|
*/
|
||||||
}
|
private void changePassword(String nameLowercase, String password, CommandSender sender) {
|
||||||
if (auth == null) {
|
PlayerAuth auth = getAuth(nameLowercase);
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
if (auth == null) {
|
||||||
return;
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
HashedPassword hashedPassword = passwordSecurity.computeHash(password, nameLowercase);
|
||||||
auth.setPassword(hashedPassword);
|
auth.setPassword(hashedPassword);
|
||||||
|
|
||||||
if (dataSource.updatePassword(auth)) {
|
if (dataSource.updatePassword(auth)) {
|
||||||
commandService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
commonService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||||
ConsoleLogger.info(sender.getName() + " changed password of " + playerNameLowerCase);
|
ConsoleLogger.info(sender.getName() + " changed password of " + nameLowercase);
|
||||||
} else {
|
} else {
|
||||||
commandService.send(sender, MessageKey.ERROR);
|
commonService.send(sender, MessageKey.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
private PlayerAuth getAuth(String nameLowercase) {
|
||||||
|
if (playerCache.isAuthenticated(nameLowercase)) {
|
||||||
|
return playerCache.getAuth(nameLowercase);
|
||||||
|
} else if (dataSource.isAuthAvailable(nameLowercase)) {
|
||||||
|
return dataSource.getAuth(nameLowercase);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import ch.jalu.injector.Injector;
|
|||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.converter.Converter;
|
import fr.xephi.authme.datasource.converter.Converter;
|
||||||
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
||||||
@ -16,6 +15,7 @@ import fr.xephi.authme.datasource.converter.vAuthConverter;
|
|||||||
import fr.xephi.authme.datasource.converter.xAuthConverter;
|
import fr.xephi.authme.datasource.converter.xAuthConverter;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -31,7 +31,7 @@ public class ConverterCommand implements ExecutableCommand {
|
|||||||
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
|
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
@ -61,7 +61,7 @@ public class ConverterCommand implements ExecutableCommand {
|
|||||||
try {
|
try {
|
||||||
converter.execute(sender);
|
converter.execute(sender);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
commandService.send(sender, MessageKey.ERROR);
|
commonService.send(sender, MessageKey.ERROR);
|
||||||
ConsoleLogger.logException("Error during conversion:", e);
|
ConsoleLogger.logException("Error during conversion:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -19,7 +19,7 @@ public class GetEmailCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||||
@ -27,7 +27,7 @@ public class GetEmailCommand implements ExecutableCommand {
|
|||||||
|
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("[AuthMe] " + playerName + "'s email: " + auth.getEmail());
|
sender.sendMessage("[AuthMe] " + playerName + "'s email: " + auth.getEmail());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -20,16 +20,16 @@ public class LastLoginCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||||
// Get the player
|
// Get the player
|
||||||
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
|
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||||
|
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
commonService.send(sender, MessageKey.USER_NOT_REGISTERED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -19,7 +19,7 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||||
@ -35,7 +35,7 @@ public class PurgeLastPositionCommand implements ExecutableCommand {
|
|||||||
// Get the user auth and make sure the user exists
|
// Get the user auth and make sure the user exists
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,13 @@ package fr.xephi.authme.command.executable.authme;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.limbo.LimboCache;
|
import fr.xephi.authme.data.limbo.LimboCache;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -27,7 +27,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
private PasswordSecurity passwordSecurity;
|
private PasswordSecurity passwordSecurity;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
@ -51,7 +51,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
// Command logic
|
// Command logic
|
||||||
ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
|
ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
|
||||||
if (passwordValidation.hasError()) {
|
if (passwordValidation.hasError()) {
|
||||||
commandService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
commonService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||||
commandService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||||
@ -71,12 +71,12 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (!dataSource.saveAuth(auth)) {
|
if (!dataSource.saveAuth(auth)) {
|
||||||
commandService.send(sender, MessageKey.ERROR);
|
commonService.send(sender, MessageKey.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dataSource.setUnlogged(playerNameLowerCase);
|
dataSource.setUnlogged(playerNameLowerCase);
|
||||||
|
|
||||||
commandService.send(sender, MessageKey.REGISTER_SUCCESS);
|
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||||
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
||||||
final Player player = bukkitService.getPlayerExact(playerName);
|
final Player player = bukkitService.getPlayerExact(playerName);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
@ -84,7 +84,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
limboCache.restoreData(player);
|
limboCache.restoreData(player);
|
||||||
player.kickPlayer(commandService.retrieveSingle(MessageKey.KICK_FOR_ADMIN_REGISTER));
|
player.kickPlayer(commonService.retrieveSingleMessage(MessageKey.KICK_FOR_ADMIN_REGISTER));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,12 @@ package fr.xephi.authme.command.executable.authme;
|
|||||||
import ch.jalu.injector.Injector;
|
import ch.jalu.injector.Injector;
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.initialization.Reloadable;
|
import fr.xephi.authme.initialization.Reloadable;
|
||||||
import fr.xephi.authme.initialization.SettingsDependent;
|
import fr.xephi.authme.initialization.SettingsDependent;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -35,7 +35,7 @@ public class ReloadCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||||
@ -48,7 +48,7 @@ public class ReloadCommand implements ExecutableCommand {
|
|||||||
sender.sendMessage("Note: cannot change database type during /authme reload");
|
sender.sendMessage("Note: cannot change database type during /authme reload");
|
||||||
}
|
}
|
||||||
performReloadOnServices();
|
performReloadOnServices();
|
||||||
commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
|
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
|
||||||
ConsoleLogger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
ConsoleLogger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -21,7 +22,7 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -29,6 +30,9 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ValidationService validationService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||||
// Get the player name and email address
|
// Get the player name and email address
|
||||||
@ -36,8 +40,8 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
final String playerEmail = arguments.get(1);
|
final String playerEmail = arguments.get(1);
|
||||||
|
|
||||||
// Validate the email address
|
// Validate the email address
|
||||||
if (!commandService.validateEmail(playerEmail)) {
|
if (!validationService.validateEmail(playerEmail)) {
|
||||||
commandService.send(sender, MessageKey.INVALID_EMAIL);
|
commonService.send(sender, MessageKey.INVALID_EMAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,17 +51,17 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
// Validate the user
|
// Validate the user
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
return;
|
return;
|
||||||
} else if (!commandService.isEmailFreeForRegistration(playerEmail, sender)) {
|
} else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) {
|
||||||
commandService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the email address
|
// Set the email address
|
||||||
auth.setEmail(playerEmail);
|
auth.setEmail(playerEmail);
|
||||||
if (!dataSource.updateEmail(auth)) {
|
if (!dataSource.updateEmail(auth)) {
|
||||||
commandService.send(sender, MessageKey.ERROR);
|
commonService.send(sender, MessageKey.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show a status message
|
// Show a status message
|
||||||
commandService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ public class UnregisterAdminCommand implements ExecutableCommand {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
@ -38,7 +38,7 @@ public class UnregisterAdminCommand implements ExecutableCommand {
|
|||||||
|
|
||||||
// Make sure the user exists
|
// Make sure the user exists
|
||||||
if (!dataSource.isAuthAvailable(playerName)) {
|
if (!dataSource.isAuthAvailable(playerName)) {
|
||||||
commandService.send(sender, MessageKey.UNKNOWN_USER);
|
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
package fr.xephi.authme.command.executable.captcha;
|
package fr.xephi.authme.command.executable.captcha;
|
||||||
|
|
||||||
|
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.CommandService;
|
import fr.xephi.authme.command.CommandService;
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
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 org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -20,7 +22,7 @@ public class CaptchaCommand extends PlayerCommand {
|
|||||||
private CaptchaManager captchaManager;
|
private CaptchaManager captchaManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboCache limboCache;
|
private LimboCache limboCache;
|
||||||
@ -30,9 +32,9 @@ public class CaptchaCommand extends PlayerCommand {
|
|||||||
final String playerName = player.getName().toLowerCase();
|
final String playerName = player.getName().toLowerCase();
|
||||||
|
|
||||||
if (playerCache.isAuthenticated(playerName)) {
|
if (playerCache.isAuthenticated(playerName)) {
|
||||||
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
} else if (!captchaManager.isCaptchaRequired(playerName)) {
|
} else if (!captchaManager.isCaptchaRequired(playerName)) {
|
||||||
commandService.send(player, MessageKey.USAGE_LOGIN);
|
commonService.send(player, MessageKey.USAGE_LOGIN);
|
||||||
} else {
|
} else {
|
||||||
checkCaptcha(player, arguments.get(0));
|
checkCaptcha(player, arguments.get(0));
|
||||||
}
|
}
|
||||||
@ -46,7 +48,7 @@ public class CaptchaCommand extends PlayerCommand {
|
|||||||
limboCache.getPlayerData(player.getName()).getMessageTask().setMuted(false);
|
limboCache.getPlayerData(player.getName()).getMessageTask().setMuted(false);
|
||||||
} else {
|
} else {
|
||||||
String newCode = captchaManager.generateCode(player.getName());
|
String newCode = captchaManager.generateCode(player.getName());
|
||||||
commandService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
commonService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.changepassword;
|
package fr.xephi.authme.command.executable.changepassword;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -18,7 +18,7 @@ import java.util.List;
|
|||||||
public class ChangePasswordCommand extends PlayerCommand {
|
public class ChangePasswordCommand extends PlayerCommand {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -36,14 +36,14 @@ public class ChangePasswordCommand extends PlayerCommand {
|
|||||||
|
|
||||||
String name = player.getName().toLowerCase();
|
String name = player.getName().toLowerCase();
|
||||||
if (!playerCache.isAuthenticated(name)) {
|
if (!playerCache.isAuthenticated(name)) {
|
||||||
commandService.send(player, MessageKey.NOT_LOGGED_IN);
|
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the password is allowed
|
// Make sure the password is allowed
|
||||||
ValidationResult passwordValidation = validationService.validatePassword(newPassword, name);
|
ValidationResult passwordValidation = validationService.validatePassword(newPassword, name);
|
||||||
if (passwordValidation.hasError()) {
|
if (passwordValidation.hasError()) {
|
||||||
commandService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
commonService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package fr.xephi.authme.command.executable.email;
|
package fr.xephi.authme.command.executable.email;
|
||||||
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -18,7 +18,7 @@ public class AddEmailCommand extends PlayerCommand {
|
|||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
@ -29,7 +29,7 @@ public class AddEmailCommand extends PlayerCommand {
|
|||||||
// Closer inspection of the mail address handled by the async task
|
// Closer inspection of the mail address handled by the async task
|
||||||
management.performAddEmail(player, email);
|
management.performAddEmail(player, email);
|
||||||
} else {
|
} else {
|
||||||
commandService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
|
commonService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
package fr.xephi.authme.command.executable.email;
|
package fr.xephi.authme.command.executable.email;
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.mail.SendMailSSL;
|
import fr.xephi.authme.mail.SendMailSSL;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.util.RandomStringUtils;
|
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.RecoveryCodeService;
|
import fr.xephi.authme.service.RecoveryCodeService;
|
||||||
|
import fr.xephi.authme.util.RandomStringUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -28,7 +28,7 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||||||
private PasswordSecurity passwordSecurity;
|
private PasswordSecurity passwordSecurity;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
@ -49,23 +49,23 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||||||
|
|
||||||
if (!sendMailSsl.hasAllInformation()) {
|
if (!sendMailSsl.hasAllInformation()) {
|
||||||
ConsoleLogger.warning("Mail API is not set");
|
ConsoleLogger.warning("Mail API is not set");
|
||||||
commandService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (playerCache.isAuthenticated(playerName)) {
|
if (playerCache.isAuthenticated(playerName)) {
|
||||||
commandService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName); // TODO: Create method to get email only
|
PlayerAuth auth = dataSource.getAuth(playerName); // TODO: Create method to get email only
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
commandService.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
|
commonService.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String email = auth.getEmail();
|
final String email = auth.getEmail();
|
||||||
if (email == null || !email.equalsIgnoreCase(playerMail) || "your@email.com".equalsIgnoreCase(email)) {
|
if (email == null || !email.equalsIgnoreCase(playerMail) || "your@email.com".equalsIgnoreCase(email)) {
|
||||||
commandService.send(player, MessageKey.INVALID_EMAIL);
|
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,28 +84,35 @@ public class RecoverEmailCommand extends PlayerCommand {
|
|||||||
|
|
||||||
private void createAndSendRecoveryCode(Player player, String email) {
|
private void createAndSendRecoveryCode(Player player, String email) {
|
||||||
String recoveryCode = recoveryCodeService.generateCode(player.getName());
|
String recoveryCode = recoveryCodeService.generateCode(player.getName());
|
||||||
sendMailSsl.sendRecoveryCode(player.getName(), email, recoveryCode);
|
boolean couldSendMail = sendMailSsl.sendRecoveryCode(player.getName(), email, recoveryCode);
|
||||||
commandService.send(player, MessageKey.RECOVERY_CODE_SENT);
|
if (couldSendMail) {
|
||||||
|
commonService.send(player, MessageKey.RECOVERY_CODE_SENT);
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processRecoveryCode(Player player, String code, String email) {
|
private void processRecoveryCode(Player player, String code, String email) {
|
||||||
final String name = player.getName();
|
final String name = player.getName();
|
||||||
if (!recoveryCodeService.isCodeValid(name, code)) {
|
if (recoveryCodeService.isCodeValid(name, code)) {
|
||||||
commandService.send(player, MessageKey.INCORRECT_RECOVERY_CODE);
|
generateAndSendNewPassword(player, email);
|
||||||
return;
|
recoveryCodeService.removeCode(name);
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.INCORRECT_RECOVERY_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateAndSendNewPassword(player, email);
|
|
||||||
recoveryCodeService.removeCode(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateAndSendNewPassword(Player player, String email) {
|
private void generateAndSendNewPassword(Player player, String email) {
|
||||||
String name = player.getName();
|
String name = player.getName();
|
||||||
String thePass = RandomStringUtils.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
String thePass = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||||
HashedPassword hashNew = passwordSecurity.computeHash(thePass, name);
|
HashedPassword hashNew = passwordSecurity.computeHash(thePass, name);
|
||||||
|
|
||||||
dataSource.updatePassword(name, hashNew);
|
dataSource.updatePassword(name, hashNew);
|
||||||
sendMailSsl.sendPasswordMail(name, email, thePass);
|
boolean couldSendMail = sendMailSsl.sendPasswordMail(name, email, thePass);
|
||||||
commandService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
if (couldSendMail) {
|
||||||
|
commonService.send(player, MessageKey.RECOVERY_EMAIL_SENT_MESSAGE);
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.email;
|
package fr.xephi.authme.command.executable.email;
|
||||||
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -14,8 +14,9 @@ import java.util.List;
|
|||||||
* Show email command.
|
* Show email command.
|
||||||
*/
|
*/
|
||||||
public class ShowEmailCommand extends PlayerCommand {
|
public class ShowEmailCommand extends PlayerCommand {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -23,10 +24,10 @@ public class ShowEmailCommand extends PlayerCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||||
if (auth.getEmail() != null && !auth.getEmail().equalsIgnoreCase("your@email.com")) {
|
if (auth.getEmail() != null && !"your@email.com".equalsIgnoreCase(auth.getEmail())) {
|
||||||
commandService.send(player, MessageKey.EMAIL_SHOW, auth.getEmail());
|
commonService.send(player, MessageKey.EMAIL_SHOW, auth.getEmail());
|
||||||
} else {
|
} else {
|
||||||
commandService.send(player, MessageKey.SHOW_NO_EMAIL);
|
commonService.send(player, MessageKey.SHOW_NO_EMAIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
package fr.xephi.authme.command.executable.register;
|
package fr.xephi.authme.command.executable.register;
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
import fr.xephi.authme.mail.SendMailSSL;
|
import fr.xephi.authme.mail.SendMailSSL;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.util.RandomStringUtils;
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import fr.xephi.authme.util.RandomStringUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -20,20 +21,26 @@ import static fr.xephi.authme.settings.properties.RegistrationSettings.ENABLE_CO
|
|||||||
import static fr.xephi.authme.settings.properties.RegistrationSettings.USE_EMAIL_REGISTRATION;
|
import static fr.xephi.authme.settings.properties.RegistrationSettings.USE_EMAIL_REGISTRATION;
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.ENABLE_PASSWORD_CONFIRMATION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command for /register.
|
||||||
|
*/
|
||||||
public class RegisterCommand extends PlayerCommand {
|
public class RegisterCommand extends PlayerCommand {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SendMailSSL sendMailSsl;
|
private SendMailSSL sendMailSsl;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ValidationService validationService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
if (commandService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
|
if (commonService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
|
||||||
//for two factor auth we don't need to check the usage
|
//for two factor auth we don't need to check the usage
|
||||||
management.performRegister(player, "", "", true);
|
management.performRegister(player, "", "", true);
|
||||||
return;
|
return;
|
||||||
@ -42,11 +49,11 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
// Ensure that there is 1 argument, or 2 if confirmation is required
|
// Ensure that there is 1 argument, or 2 if confirmation is required
|
||||||
final boolean useConfirmation = isConfirmationRequired();
|
final boolean useConfirmation = isConfirmationRequired();
|
||||||
if (arguments.isEmpty() || useConfirmation && arguments.size() < 2) {
|
if (arguments.isEmpty() || useConfirmation && arguments.size() < 2) {
|
||||||
commandService.send(player, MessageKey.USAGE_REGISTER);
|
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandService.getProperty(USE_EMAIL_REGISTRATION)) {
|
if (commonService.getProperty(USE_EMAIL_REGISTRATION)) {
|
||||||
handleEmailRegistration(player, arguments);
|
handleEmailRegistration(player, arguments);
|
||||||
} else {
|
} else {
|
||||||
handlePasswordRegistration(player, arguments);
|
handlePasswordRegistration(player, arguments);
|
||||||
@ -59,8 +66,8 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handlePasswordRegistration(Player player, List<String> arguments) {
|
private void handlePasswordRegistration(Player player, List<String> arguments) {
|
||||||
if (commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
|
if (commonService.getProperty(ENABLE_PASSWORD_CONFIRMATION) && !arguments.get(0).equals(arguments.get(1))) {
|
||||||
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
commonService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
||||||
} else {
|
} else {
|
||||||
management.performRegister(player, arguments.get(0), "", true);
|
management.performRegister(player, arguments.get(0), "", true);
|
||||||
}
|
}
|
||||||
@ -68,19 +75,19 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
|
|
||||||
private void handleEmailRegistration(Player player, List<String> arguments) {
|
private void handleEmailRegistration(Player player, List<String> arguments) {
|
||||||
if (!sendMailSsl.hasAllInformation()) {
|
if (!sendMailSsl.hasAllInformation()) {
|
||||||
commandService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||||
ConsoleLogger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
ConsoleLogger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
||||||
+ "to send emails from. Please adjust your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
|
+ "to send emails from. Please adjust your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String email = arguments.get(0);
|
final String email = arguments.get(0);
|
||||||
if (!commandService.validateEmail(email)) {
|
if (!validationService.validateEmail(email)) {
|
||||||
commandService.send(player, MessageKey.INVALID_EMAIL);
|
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||||
} else if (commandService.getProperty(ENABLE_CONFIRM_EMAIL) && !email.equals(arguments.get(1))) {
|
} else if (commonService.getProperty(ENABLE_CONFIRM_EMAIL) && !email.equals(arguments.get(1))) {
|
||||||
commandService.send(player, MessageKey.USAGE_REGISTER);
|
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||||
} else {
|
} else {
|
||||||
String thePass = RandomStringUtils.generate(commandService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
String thePass = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||||
management.performRegister(player, thePass, email, true);
|
management.performRegister(player, thePass, email, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,8 +98,8 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
* @return True if the confirmation is needed, false otherwise
|
* @return True if the confirmation is needed, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean isConfirmationRequired() {
|
private boolean isConfirmationRequired() {
|
||||||
return commandService.getProperty(USE_EMAIL_REGISTRATION)
|
return commonService.getProperty(USE_EMAIL_REGISTRATION)
|
||||||
? commandService.getProperty(ENABLE_CONFIRM_EMAIL)
|
? commonService.getProperty(ENABLE_CONFIRM_EMAIL)
|
||||||
: commandService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
|
: commonService.getProperty(ENABLE_PASSWORD_CONFIRMATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.unregister;
|
package fr.xephi.authme.command.executable.unregister;
|
||||||
|
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
|
||||||
import fr.xephi.authme.command.CommandService;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -19,7 +19,7 @@ public class UnregisterCommand extends PlayerCommand {
|
|||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommandService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -31,7 +31,7 @@ public class UnregisterCommand extends PlayerCommand {
|
|||||||
|
|
||||||
// Make sure the player is authenticated
|
// Make sure the player is authenticated
|
||||||
if (!playerCache.isAuthenticated(playerName)) {
|
if (!playerCache.isAuthenticated(playerName)) {
|
||||||
commandService.send(player, MessageKey.NOT_LOGGED_IN);
|
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -189,7 +189,7 @@ public class PlayerAuth {
|
|||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public String serialize() {
|
public String serialize() {
|
||||||
StringBuffer str = new StringBuffer();
|
StringBuilder str = new StringBuilder();
|
||||||
char d = ';';
|
char d = ';';
|
||||||
str.append(this.nickname).append(d);
|
str.append(this.nickname).append(d);
|
||||||
str.append(this.realName).append(d);
|
str.append(this.realName).append(d);
|
||||||
|
|||||||
@ -84,10 +84,10 @@ public class LimboCache {
|
|||||||
float walkSpeed = data.getWalkSpeed();
|
float walkSpeed = data.getWalkSpeed();
|
||||||
float flySpeed = data.getFlySpeed();
|
float flySpeed = data.getFlySpeed();
|
||||||
// Reset the speed value if it was 0
|
// Reset the speed value if it was 0
|
||||||
if(walkSpeed == 0f) {
|
if(walkSpeed < 0.01f) {
|
||||||
walkSpeed = 0.2f;
|
walkSpeed = 0.2f;
|
||||||
}
|
}
|
||||||
if(flySpeed == 0f) {
|
if(flySpeed < 0.01f) {
|
||||||
flySpeed = 0.2f;
|
flySpeed = 0.2f;
|
||||||
}
|
}
|
||||||
player.setWalkSpeed(walkSpeed);
|
player.setWalkSpeed(walkSpeed);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package fr.xephi.authme.datasource;
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
@ -11,15 +10,13 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSourceType;
|
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -48,17 +45,12 @@ public class CacheDataSource implements DataSource {
|
|||||||
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
|
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
|
||||||
@Override
|
@Override
|
||||||
public Optional<PlayerAuth> load(String key) {
|
public Optional<PlayerAuth> load(String key) {
|
||||||
return Optional.fromNullable(source.getAuth(key));
|
return Optional.ofNullable(source.getAuth(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
|
public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
|
||||||
return executorService.submit(new Callable<Optional<PlayerAuth>>() {
|
return executorService.submit(() -> load(key));
|
||||||
@Override
|
|
||||||
public Optional<PlayerAuth> call() {
|
|
||||||
return load(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -90,7 +82,7 @@ public class CacheDataSource implements DataSource {
|
|||||||
@Override
|
@Override
|
||||||
public PlayerAuth getAuth(String user) {
|
public PlayerAuth getAuth(String user) {
|
||||||
user = user.toLowerCase();
|
user = user.toLowerCase();
|
||||||
return cachedAuths.getUnchecked(user).orNull();
|
return cachedAuths.getUnchecked(user).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import java.io.BufferedReader;
|
|||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -295,19 +294,11 @@ public class FlatFile implements DataSource {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.warning(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.warning(ex.getMessage());
|
ConsoleLogger.warning(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (newAuth != null) {
|
if (newAuth != null) {
|
||||||
removeAuth(auth.getNickname());
|
removeAuth(auth.getNickname());
|
||||||
@ -330,19 +321,11 @@ public class FlatFile implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return countIp;
|
return countIp;
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.warning(ex.getMessage());
|
|
||||||
return new ArrayList<>();
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.warning(ex.getMessage());
|
ConsoleLogger.warning(ex.getMessage());
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,12 +346,7 @@ public class FlatFile implements DataSource {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.warning(ex.getMessage());
|
ConsoleLogger.warning(ex.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,6 @@ import com.zaxxer.hikari.HikariDataSource;
|
|||||||
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.Columns;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSourceType;
|
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.security.crypts.XFBCRYPT;
|
import fr.xephi.authme.security.crypts.XFBCRYPT;
|
||||||
@ -15,8 +12,8 @@ import fr.xephi.authme.settings.Settings;
|
|||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import fr.xephi.authme.util.RuntimeUtils;
|
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
import fr.xephi.authme.util.Utils;
|
||||||
|
|
||||||
import java.sql.Blob;
|
import java.sql.Blob;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@ -50,7 +47,7 @@ public class MySQL implements DataSource {
|
|||||||
private int phpBbGroup;
|
private int phpBbGroup;
|
||||||
private String wordpressPrefix;
|
private String wordpressPrefix;
|
||||||
|
|
||||||
public MySQL(Settings settings) throws ClassNotFoundException, SQLException, PoolInitializationException {
|
public MySQL(Settings settings) throws ClassNotFoundException, SQLException {
|
||||||
setParameters(settings);
|
setParameters(settings);
|
||||||
|
|
||||||
// Set the connection arguments (and check if connection is ok)
|
// Set the connection arguments (and check if connection is ok)
|
||||||
@ -100,17 +97,17 @@ public class MySQL implements DataSource {
|
|||||||
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
|
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
|
||||||
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
|
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
|
||||||
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
||||||
if(poolSize == -1) {
|
if (poolSize == -1) {
|
||||||
poolSize = RuntimeUtils.getCoreCount();
|
poolSize = Utils.getCoreCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setConnectionArguments() throws RuntimeException {
|
private void setConnectionArguments() {
|
||||||
ds = new HikariDataSource();
|
ds = new HikariDataSource();
|
||||||
ds.setPoolName("AuthMeMYSQLPool");
|
ds.setPoolName("AuthMeMYSQLPool");
|
||||||
|
|
||||||
// Pool size
|
// Pool size
|
||||||
ds.setMaximumPoolSize(poolSize);
|
ds.setMaximumPoolSize(poolSize);
|
||||||
|
|
||||||
// Database URL
|
// Database URL
|
||||||
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
|
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
|
||||||
@ -137,7 +134,7 @@ public class MySQL implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() throws RuntimeException {
|
public void reload() {
|
||||||
if (ds != null) {
|
if (ds != null) {
|
||||||
ds.close();
|
ds.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@ package fr.xephi.authme.datasource;
|
|||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.Columns;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSourceType;
|
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
@ -397,7 +394,7 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(Statement st) {
|
private static void close(Statement st) {
|
||||||
if (st != null) {
|
if (st != null) {
|
||||||
try {
|
try {
|
||||||
st.close();
|
st.close();
|
||||||
@ -407,7 +404,7 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(Connection con) {
|
private static void close(Connection con) {
|
||||||
if (con != null) {
|
if (con != null) {
|
||||||
try {
|
try {
|
||||||
con.close();
|
con.close();
|
||||||
@ -417,7 +414,7 @@ public class SQLite implements DataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(ResultSet rs) {
|
private static void close(ResultSet rs) {
|
||||||
if (rs != null) {
|
if (rs != null) {
|
||||||
try {
|
try {
|
||||||
rs.close();
|
rs.close();
|
||||||
@ -479,7 +476,7 @@ public class SQLite implements DataSource {
|
|||||||
pst.setString(1, user);
|
pst.setString(1, user);
|
||||||
rs = pst.executeQuery();
|
rs = pst.executeQuery();
|
||||||
if (rs.next())
|
if (rs.next())
|
||||||
return (rs.getInt(col.IS_LOGGED) == 1);
|
return rs.getInt(col.IS_LOGGED) == 1;
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
logSqlException(ex);
|
logSqlException(ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -43,20 +43,7 @@ public class CrazyLoginConverter implements Converter {
|
|||||||
try (BufferedReader users = new BufferedReader(new FileReader(source))) {
|
try (BufferedReader users = new BufferedReader(new FileReader(source))) {
|
||||||
while ((line = users.readLine()) != null) {
|
while ((line = users.readLine()) != null) {
|
||||||
if (line.contains("|")) {
|
if (line.contains("|")) {
|
||||||
String[] args = line.split("\\|");
|
migrateAccount(line);
|
||||||
if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String playerName = args[0];
|
|
||||||
String password = args[1];
|
|
||||||
if (password != null) {
|
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
|
||||||
.name(playerName.toLowerCase())
|
|
||||||
.realName(playerName)
|
|
||||||
.password(password, null)
|
|
||||||
.build();
|
|
||||||
database.saveAuth(auth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConsoleLogger.info("CrazyLogin database has been imported correctly");
|
ConsoleLogger.info("CrazyLogin database has been imported correctly");
|
||||||
@ -66,4 +53,26 @@ public class CrazyLoginConverter implements Converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves an account from CrazyLogin to the AuthMe database.
|
||||||
|
*
|
||||||
|
* @param line line read from the CrazyLogin file (one account)
|
||||||
|
*/
|
||||||
|
private void migrateAccount(String line) {
|
||||||
|
String[] args = line.split("\\|");
|
||||||
|
if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String playerName = args[0];
|
||||||
|
String password = args[1];
|
||||||
|
if (password != null) {
|
||||||
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
|
.name(playerName.toLowerCase())
|
||||||
|
.realName(playerName)
|
||||||
|
.password(password, null)
|
||||||
|
.build();
|
||||||
|
database.saveAuth(auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,123 @@
|
|||||||
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.datasource.CacheDataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSourceType;
|
||||||
|
import fr.xephi.authme.datasource.FlatFile;
|
||||||
|
import fr.xephi.authme.datasource.MySQL;
|
||||||
|
import fr.xephi.authme.datasource.SQLite;
|
||||||
|
import fr.xephi.authme.datasource.converter.ForceFlatToSqlite;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the AuthMe data source.
|
||||||
|
*/
|
||||||
|
public class DataSourceProvider implements Provider<DataSource> {
|
||||||
|
|
||||||
|
private static final String FLATFILE_FILENAME = "auths.db";
|
||||||
|
private static final int SQLITE_MAX_SIZE = 4000;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@DataFolder
|
||||||
|
private File dataFolder;
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
|
||||||
|
DataSourceProvider() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSource get() {
|
||||||
|
try {
|
||||||
|
return createDataSource();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ConsoleLogger.logException("Could not create data source:", e);
|
||||||
|
throw new IllegalStateException("Error during initialization of data source", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the data source.
|
||||||
|
*
|
||||||
|
* @return the constructed datasource
|
||||||
|
* @throws ClassNotFoundException if no driver could be found for the datasource
|
||||||
|
* @throws SQLException when initialization of a SQL datasource failed
|
||||||
|
* @throws IOException if flat file cannot be read
|
||||||
|
*/
|
||||||
|
private DataSource createDataSource() throws ClassNotFoundException, SQLException, IOException {
|
||||||
|
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
|
||||||
|
DataSource dataSource;
|
||||||
|
switch (dataSourceType) {
|
||||||
|
case FILE:
|
||||||
|
File source = new File(dataFolder, FLATFILE_FILENAME);
|
||||||
|
dataSource = new FlatFile(source);
|
||||||
|
break;
|
||||||
|
case MYSQL:
|
||||||
|
dataSource = new MySQL(settings);
|
||||||
|
break;
|
||||||
|
case SQLITE:
|
||||||
|
dataSource = new SQLite(settings);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSource = convertFlatfileToSqlite(dataSource);
|
||||||
|
|
||||||
|
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
|
||||||
|
dataSource = new CacheDataSource(dataSource);
|
||||||
|
}
|
||||||
|
if (DataSourceType.SQLITE.equals(dataSourceType)) {
|
||||||
|
checkDataSourceSize(dataSource, bukkitService);
|
||||||
|
}
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDataSourceSize(final DataSource dataSource, BukkitService bukkitService) {
|
||||||
|
bukkitService.runTaskAsynchronously(() -> {
|
||||||
|
int accounts = dataSource.getAccountsRegistered();
|
||||||
|
if (accounts >= SQLITE_MAX_SIZE) {
|
||||||
|
ConsoleLogger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
||||||
|
+ accounts + "+ ACCOUNTS; FOR BETTER PERFORMANCE, PLEASE UPGRADE TO MYSQL!!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the data source from the deprecated FLATFILE type to SQLITE.
|
||||||
|
*
|
||||||
|
* @param dataSource the data source to convert if necessary
|
||||||
|
* @return the data source to use: the converted datasource (SQLite),
|
||||||
|
* or the same data source if no conversion was performed
|
||||||
|
*/
|
||||||
|
private DataSource convertFlatfileToSqlite(DataSource dataSource) {
|
||||||
|
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
|
||||||
|
ConsoleLogger.warning("FlatFile backend has been detected and is now deprecated; it will be changed "
|
||||||
|
+ "to SQLite... Connection will be impossible until conversion is done!");
|
||||||
|
FlatFile flatFile = (FlatFile) dataSource;
|
||||||
|
try {
|
||||||
|
SQLite sqlite = new SQLite(settings);
|
||||||
|
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
|
||||||
|
converter.execute(null);
|
||||||
|
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
|
||||||
|
settings.save();
|
||||||
|
return sqlite;
|
||||||
|
} catch (Exception e) {
|
||||||
|
ConsoleLogger.logException("Error during conversion from Flatfile to SQLite", e);
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,8 @@ package fr.xephi.authme.initialization;
|
|||||||
/**
|
/**
|
||||||
* Common interface for types which have data that becomes outdated
|
* Common interface for types which have data that becomes outdated
|
||||||
* and that can be cleaned up periodically.
|
* and that can be cleaned up periodically.
|
||||||
|
*
|
||||||
|
* @see fr.xephi.authme.task.CleanupTask
|
||||||
*/
|
*/
|
||||||
public interface HasCleanup {
|
public interface HasCleanup {
|
||||||
|
|
||||||
|
|||||||
@ -1,176 +0,0 @@
|
|||||||
package fr.xephi.authme.initialization;
|
|
||||||
|
|
||||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
|
||||||
import com.github.authme.configme.resource.PropertyResource;
|
|
||||||
import com.github.authme.configme.resource.YamlFileResource;
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.datasource.CacheDataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.datasource.DataSourceType;
|
|
||||||
import fr.xephi.authme.datasource.FlatFile;
|
|
||||||
import fr.xephi.authme.datasource.MySQL;
|
|
||||||
import fr.xephi.authme.datasource.SQLite;
|
|
||||||
import fr.xephi.authme.message.MessageKey;
|
|
||||||
import fr.xephi.authme.message.Messages;
|
|
||||||
import fr.xephi.authme.output.ConsoleFilter;
|
|
||||||
import fr.xephi.authme.output.Log4JFilter;
|
|
||||||
import fr.xephi.authme.service.BukkitService;
|
|
||||||
import fr.xephi.authme.service.MigrationService;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.settings.SettingsMigrationService;
|
|
||||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
|
||||||
import fr.xephi.authme.util.FileUtils;
|
|
||||||
import fr.xephi.authme.util.StringUtils;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
|
||||||
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes various services.
|
|
||||||
*/
|
|
||||||
public class Initializer {
|
|
||||||
|
|
||||||
private static final String FLATFILE_FILENAME = "auths.db";
|
|
||||||
private static final int SQLITE_MAX_SIZE = 4000;
|
|
||||||
|
|
||||||
private AuthMe authMe;
|
|
||||||
private BukkitService bukkitService;
|
|
||||||
|
|
||||||
public Initializer(AuthMe authMe, BukkitService bukkitService) {
|
|
||||||
this.authMe = authMe;
|
|
||||||
this.bukkitService = bukkitService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the plugin's settings.
|
|
||||||
*
|
|
||||||
* @param authMe the plugin instance
|
|
||||||
* @return the settings instance, or null if it could not be constructed
|
|
||||||
*/
|
|
||||||
public static Settings createSettings(AuthMe authMe) throws Exception {
|
|
||||||
File configFile = new File(authMe.getDataFolder(), "config.yml");
|
|
||||||
if(!configFile.exists()) {
|
|
||||||
configFile.createNewFile();
|
|
||||||
}
|
|
||||||
PropertyResource resource = new YamlFileResource(configFile);
|
|
||||||
SettingsMigrationService migrationService = new SettingsMigrationService(authMe.getDataFolder());
|
|
||||||
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
|
||||||
return new Settings(authMe.getDataFolder(), resource, migrationService, configurationData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the data source.
|
|
||||||
*
|
|
||||||
* @param settings the settings
|
|
||||||
* @return the constructed datasource
|
|
||||||
* @throws ClassNotFoundException if no driver could be found for the datasource
|
|
||||||
* @throws SQLException when initialization of a SQL datasource failed
|
|
||||||
* @throws IOException if flat file cannot be read
|
|
||||||
*/
|
|
||||||
public DataSource setupDatabase(Settings settings) throws ClassNotFoundException, SQLException, IOException {
|
|
||||||
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
|
|
||||||
DataSource dataSource;
|
|
||||||
switch (dataSourceType) {
|
|
||||||
case FILE:
|
|
||||||
File source = new File(authMe.getDataFolder(), FLATFILE_FILENAME);
|
|
||||||
dataSource = new FlatFile(source);
|
|
||||||
break;
|
|
||||||
case MYSQL:
|
|
||||||
dataSource = new MySQL(settings);
|
|
||||||
break;
|
|
||||||
case SQLITE:
|
|
||||||
dataSource = new SQLite(settings);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
DataSource convertedSource = MigrationService.convertFlatfileToSqlite(settings, dataSource);
|
|
||||||
dataSource = convertedSource == null ? dataSource : convertedSource;
|
|
||||||
|
|
||||||
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
|
|
||||||
dataSource = new CacheDataSource(dataSource);
|
|
||||||
}
|
|
||||||
if (DataSourceType.SQLITE.equals(dataSourceType)) {
|
|
||||||
checkDataSourceSize(dataSource);
|
|
||||||
}
|
|
||||||
return dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDataSourceSize(final DataSource dataSource) {
|
|
||||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int accounts = dataSource.getAccountsRegistered();
|
|
||||||
if (accounts >= SQLITE_MAX_SIZE) {
|
|
||||||
ConsoleLogger.warning("YOU'RE USING THE SQLITE DATABASE WITH "
|
|
||||||
+ accounts + "+ ACCOUNTS; FOR BETTER PERFORMANCE, PLEASE UPGRADE TO MYSQL!!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up the console filter if enabled.
|
|
||||||
*
|
|
||||||
* @param settings the settings
|
|
||||||
* @param logger the plugin logger
|
|
||||||
*/
|
|
||||||
public void setupConsoleFilter(Settings settings, Logger logger) {
|
|
||||||
if (!settings.getProperty(SecuritySettings.REMOVE_PASSWORD_FROM_CONSOLE)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Try to set the log4j filter
|
|
||||||
try {
|
|
||||||
Class.forName("org.apache.logging.log4j.core.filter.AbstractFilter");
|
|
||||||
setLog4JFilter();
|
|
||||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
|
||||||
// log4j is not available
|
|
||||||
ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
|
||||||
ConsoleFilter filter = new ConsoleFilter();
|
|
||||||
logger.setFilter(filter);
|
|
||||||
Bukkit.getLogger().setFilter(filter);
|
|
||||||
Logger.getLogger("Minecraft").setFilter(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the console filter to remove the passwords
|
|
||||||
private static void setLog4JFilter() {
|
|
||||||
org.apache.logging.log4j.core.Logger logger;
|
|
||||||
logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
|
|
||||||
logger.addFilter(new Log4JFilter());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleRecallEmailTask(Settings settings, final DataSource dataSource, final Messages messages) {
|
|
||||||
if (!settings.getProperty(RECALL_PLAYERS)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bukkitService.runTaskTimerAsynchronously(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (PlayerAuth auth : dataSource.getLoggedPlayers()) {
|
|
||||||
String email = auth.getEmail();
|
|
||||||
if (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email)) {
|
|
||||||
Player player = bukkitService.getPlayerExact(auth.getRealName());
|
|
||||||
if (player != null) {
|
|
||||||
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
package fr.xephi.authme.initialization;
|
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
|
||||||
import org.mcstats.Metrics;
|
|
||||||
import org.mcstats.Metrics.Graph;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class MetricsManager {
|
|
||||||
|
|
||||||
private MetricsManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendMetrics(AuthMe plugin, Settings settings) {
|
|
||||||
try {
|
|
||||||
final Metrics metrics = new Metrics(plugin);
|
|
||||||
|
|
||||||
final Graph languageGraph = metrics.createGraph("Messages Language");
|
|
||||||
final String messagesLanguage = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
|
||||||
languageGraph.addPlotter(new Metrics.Plotter(messagesLanguage) {
|
|
||||||
@Override
|
|
||||||
public int getValue() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final Graph databaseBackend = metrics.createGraph("Database Backend");
|
|
||||||
final String dataSource = settings.getProperty(DatabaseSettings.BACKEND).toString();
|
|
||||||
databaseBackend.addPlotter(new Metrics.Plotter(dataSource) {
|
|
||||||
@Override
|
|
||||||
public int getValue() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Submit metrics
|
|
||||||
metrics.start();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Failed to submit the metrics data
|
|
||||||
ConsoleLogger.logException("Can't send Metrics data! The plugin will work anyway...", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -76,10 +76,8 @@ public class OnShutdownPlayerSaver {
|
|||||||
dataSource.updateQuitLoc(auth);
|
dataSource.updateQuitLoc(auth);
|
||||||
}
|
}
|
||||||
if (settings.getProperty(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN)
|
if (settings.getProperty(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN)
|
||||||
&& !settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
&& !settings.getProperty(RestrictionSettings.NO_TELEPORT) && !limboPlayerStorage.hasData(player)) {
|
||||||
if (!limboPlayerStorage.hasData(player)) {
|
limboPlayerStorage.saveData(player);
|
||||||
limboPlayerStorage.saveData(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
127
src/main/java/fr/xephi/authme/initialization/OnStartupTasks.java
Normal file
127
src/main/java/fr/xephi/authme/initialization/OnStartupTasks.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.message.Messages;
|
||||||
|
import fr.xephi.authme.output.ConsoleFilter;
|
||||||
|
import fr.xephi.authme.output.Log4JFilter;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.mcstats.Metrics;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||||
|
import static fr.xephi.authme.settings.properties.EmailSettings.RECALL_PLAYERS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains actions such as migrations that should be performed on startup.
|
||||||
|
*/
|
||||||
|
public class OnStartupTasks {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private DataSource dataSource;
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
@Inject
|
||||||
|
private Messages messages;
|
||||||
|
|
||||||
|
OnStartupTasks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendMetrics(AuthMe plugin, Settings settings) {
|
||||||
|
try {
|
||||||
|
final Metrics metrics = new Metrics(plugin);
|
||||||
|
|
||||||
|
final Metrics.Graph languageGraph = metrics.createGraph("Messages Language");
|
||||||
|
final String messagesLanguage = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
||||||
|
languageGraph.addPlotter(new Metrics.Plotter(messagesLanguage) {
|
||||||
|
@Override
|
||||||
|
public int getValue() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final Metrics.Graph databaseBackend = metrics.createGraph("Database Backend");
|
||||||
|
final String dataSource = settings.getProperty(DatabaseSettings.BACKEND).toString();
|
||||||
|
databaseBackend.addPlotter(new Metrics.Plotter(dataSource) {
|
||||||
|
@Override
|
||||||
|
public int getValue() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Submit metrics
|
||||||
|
metrics.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Failed to submit the metrics data
|
||||||
|
ConsoleLogger.logException("Can't send Metrics data! The plugin will work anyway...", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the console filter if enabled.
|
||||||
|
*
|
||||||
|
* @param settings the settings
|
||||||
|
* @param logger the plugin logger
|
||||||
|
*/
|
||||||
|
public static void setupConsoleFilter(Settings settings, Logger logger) {
|
||||||
|
if (!settings.getProperty(SecuritySettings.REMOVE_PASSWORD_FROM_CONSOLE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Try to set the log4j filter
|
||||||
|
try {
|
||||||
|
Class.forName("org.apache.logging.log4j.core.filter.AbstractFilter");
|
||||||
|
setLog4JFilter();
|
||||||
|
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||||
|
// log4j is not available
|
||||||
|
ConsoleLogger.info("You're using Minecraft 1.6.x or older, Log4J support will be disabled");
|
||||||
|
ConsoleFilter filter = new ConsoleFilter();
|
||||||
|
logger.setFilter(filter);
|
||||||
|
Bukkit.getLogger().setFilter(filter);
|
||||||
|
Logger.getLogger("Minecraft").setFilter(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the console filter to remove the passwords
|
||||||
|
private static void setLog4JFilter() {
|
||||||
|
org.apache.logging.log4j.core.Logger logger;
|
||||||
|
logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
|
||||||
|
logger.addFilter(new Log4JFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleRecallEmailTask() {
|
||||||
|
if (!settings.getProperty(RECALL_PLAYERS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bukkitService.runTaskTimerAsynchronously(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (PlayerAuth auth : dataSource.getLoggedPlayers()) {
|
||||||
|
String email = auth.getEmail();
|
||||||
|
if (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email)) {
|
||||||
|
Player player = bukkitService.getPlayerExact(auth.getRealName());
|
||||||
|
if (player != null) {
|
||||||
|
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,8 @@ package fr.xephi.authme.initialization;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for reloadable entities.
|
* Interface for reloadable entities.
|
||||||
|
*
|
||||||
|
* @see fr.xephi.authme.command.executable.authme.ReloadCommand
|
||||||
*/
|
*/
|
||||||
public interface Reloadable {
|
public interface Reloadable {
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import fr.xephi.authme.settings.Settings;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for classes that keep a local copy of certain settings.
|
* Interface for classes that keep a local copy of certain settings.
|
||||||
|
*
|
||||||
|
* @see fr.xephi.authme.command.executable.authme.ReloadCommand
|
||||||
*/
|
*/
|
||||||
public interface SettingsDependent {
|
public interface SettingsDependent {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
|
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||||
|
import com.github.authme.configme.resource.PropertyResource;
|
||||||
|
import com.github.authme.configme.resource.YamlFileResource;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.SettingsMigrationService;
|
||||||
|
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||||
|
import fr.xephi.authme.util.FileUtils;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the settings.
|
||||||
|
*/
|
||||||
|
public class SettingsProvider implements Provider<Settings> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@DataFolder
|
||||||
|
private File dataFolder;
|
||||||
|
@Inject
|
||||||
|
private SettingsMigrationService migrationService;
|
||||||
|
|
||||||
|
SettingsProvider() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the plugin's settings.
|
||||||
|
*
|
||||||
|
* @return the settings instance, or null if it could not be constructed
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Settings get() {
|
||||||
|
File configFile = new File(dataFolder, "config.yml");
|
||||||
|
if (!configFile.exists()) {
|
||||||
|
FileUtils.create(configFile);
|
||||||
|
}
|
||||||
|
PropertyResource resource = new YamlFileResource(configFile);
|
||||||
|
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||||
|
return new Settings(dataFolder, resource, migrationService, configurationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,14 +9,14 @@ import fr.xephi.authme.message.Messages;
|
|||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||||
import fr.xephi.authme.service.AntiBotService;
|
import fr.xephi.authme.service.AntiBotService;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
import fr.xephi.authme.util.Utils;
|
import fr.xephi.authme.util.Utils;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
@ -68,10 +68,10 @@ class OnJoinVerifier implements Reloadable {
|
|||||||
* @param isAuthAvailable whether or not the player is registered
|
* @param isAuthAvailable whether or not the player is registered
|
||||||
*/
|
*/
|
||||||
public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException {
|
public void checkAntibot(Player player, boolean isAuthAvailable) throws FailedVerificationException {
|
||||||
if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
if (isAuthAvailable || permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (antiBotService.shouldKick(isAuthAvailable)) {
|
if (antiBotService.shouldKick()) {
|
||||||
antiBotService.addPlayerKick(player.getName());
|
antiBotService.addPlayerKick(player.getName());
|
||||||
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
|
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
|
||||||
}
|
}
|
||||||
@ -170,10 +170,9 @@ class OnJoinVerifier implements Reloadable {
|
|||||||
public void checkPlayerCountry(boolean isAuthAvailable,
|
public void checkPlayerCountry(boolean isAuthAvailable,
|
||||||
String playerIp) throws FailedVerificationException {
|
String playerIp) throws FailedVerificationException {
|
||||||
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
|
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
|
||||||
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)) {
|
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)
|
||||||
if (!validationService.isCountryAdmitted(playerIp)) {
|
&& !validationService.isCountryAdmitted(playerIp)) {
|
||||||
throw new FailedVerificationException(MessageKey.COUNTRY_BANNED_ERROR);
|
throw new FailedVerificationException(MessageKey.COUNTRY_BANNED_ERROR);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,14 +6,14 @@ import fr.xephi.authme.message.MessageKey;
|
|||||||
import fr.xephi.authme.message.Messages;
|
import fr.xephi.authme.message.Messages;
|
||||||
import fr.xephi.authme.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
import fr.xephi.authme.service.AntiBotService;
|
import fr.xephi.authme.service.AntiBotService;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.TeleportationService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
|
||||||
import fr.xephi.authme.service.TeleportationService;
|
|
||||||
import fr.xephi.authme.service.ValidationService;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -42,6 +42,7 @@ import org.bukkit.event.player.PlayerShearEntityEvent;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAU
|
|||||||
*/
|
*/
|
||||||
public class PlayerListener implements Listener {
|
public class PlayerListener implements Listener {
|
||||||
|
|
||||||
public static final ConcurrentHashMap<String, String> joinMessage = new ConcurrentHashMap<>();
|
public static final Map<String, String> joinMessage = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
@ -81,7 +82,7 @@ public class PlayerListener implements Listener {
|
|||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||||
String cmd = event.getMessage().split(" ")[0].toLowerCase();
|
String cmd = event.getMessage().split(" ")[0].toLowerCase();
|
||||||
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && cmd.equals("/motd")) {
|
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && "/motd".equals(cmd)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
|
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
|
||||||
@ -113,7 +114,7 @@ public class PlayerListener implements Listener {
|
|||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (recipients.size() == 0) {
|
if (recipients.isEmpty()) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,9 +157,7 @@ public class PlayerListener implements Listener {
|
|||||||
if (spawn != null && spawn.getWorld() != null) {
|
if (spawn != null && spawn.getWorld() != null) {
|
||||||
if (!player.getWorld().equals(spawn.getWorld())) {
|
if (!player.getWorld().equals(spawn.getWorld())) {
|
||||||
player.teleport(spawn);
|
player.teleport(spawn);
|
||||||
return;
|
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||||
}
|
|
||||||
if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
|
||||||
player.teleport(spawn);
|
player.teleport(spawn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,9 +207,11 @@ public class PlayerListener implements Listener {
|
|||||||
final String name = player.getName();
|
final String name = player.getName();
|
||||||
if (validationService.isUnrestricted(name)) {
|
if (validationService.isUnrestricted(name)) {
|
||||||
return;
|
return;
|
||||||
} else if (onJoinVerifier.refusePlayerForFullServer(event)) {
|
}
|
||||||
|
if (onJoinVerifier.refusePlayerForFullServer(event)) {
|
||||||
return;
|
return;
|
||||||
} else if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
}
|
||||||
|
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,9 +223,9 @@ public class PlayerListener implements Listener {
|
|||||||
// Get the auth later as this may cause the single session check to fail
|
// Get the auth later as this may cause the single session check to fail
|
||||||
// Slow stuff
|
// Slow stuff
|
||||||
final PlayerAuth auth = dataSource.getAuth(name);
|
final PlayerAuth auth = dataSource.getAuth(name);
|
||||||
final boolean isAuthAvailable = (auth != null);
|
final boolean isAuthAvailable = auth != null;
|
||||||
onJoinVerifier.checkAntibot(player, isAuthAvailable);
|
|
||||||
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
|
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
|
||||||
|
onJoinVerifier.checkAntibot(player, isAuthAvailable);
|
||||||
onJoinVerifier.checkNameCasing(player, auth);
|
onJoinVerifier.checkNameCasing(player, auth);
|
||||||
onJoinVerifier.checkPlayerCountry(isAuthAvailable, event.getAddress().getHostAddress());
|
onJoinVerifier.checkPlayerCountry(isAuthAvailable, event.getAddress().getHostAddress());
|
||||||
} catch (FailedVerificationException e) {
|
} catch (FailedVerificationException e) {
|
||||||
@ -233,7 +234,6 @@ public class PlayerListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
antiBotService.handlePlayerJoin();
|
|
||||||
teleportationService.teleportOnJoin(player);
|
teleportationService.teleportOnJoin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,27 +306,14 @@ public class PlayerListener implements Listener {
|
|||||||
* @note little hack cause InventoryOpenEvent cannot be cancelled for
|
* @note little hack cause InventoryOpenEvent cannot be cancelled for
|
||||||
* real, cause no packet is send to server by client for the main inv
|
* real, cause no packet is send to server by client for the main inv
|
||||||
*/
|
*/
|
||||||
bukkitService.scheduleSyncDelayedTask(new Runnable() {
|
bukkitService.scheduleSyncDelayedTask(player::closeInventory, 1);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
player.closeInventory();
|
|
||||||
}
|
|
||||||
}, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerInventoryClick(InventoryClickEvent event) {
|
public void onPlayerInventoryClick(InventoryClickEvent event) {
|
||||||
if (event.getWhoClicked() == null) {
|
if (listenerService.shouldCancelEvent(event.getWhoClicked())) {
|
||||||
return;
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
if (!(event.getWhoClicked() instanceof Player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Player player = (Player) event.getWhoClicked();
|
|
||||||
if (!listenerService.shouldCancelEvent(player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.EntityAirChangeEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener of player events for events introduced in Minecraft 1.11.
|
||||||
|
*/
|
||||||
|
public class PlayerListener111 implements Listener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ListenerService listenerService;
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerAirChange(EntityAirChangeEvent event) {
|
||||||
|
if (listenerService.shouldCancelEvent(event)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,19 +1,22 @@
|
|||||||
package fr.xephi.authme.mail;
|
package fr.xephi.authme.mail;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
|
||||||
import fr.xephi.authme.util.FileUtils;
|
import fr.xephi.authme.util.FileUtils;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
import org.apache.commons.mail.EmailConstants;
|
import org.apache.commons.mail.EmailConstants;
|
||||||
import org.apache.commons.mail.EmailException;
|
import org.apache.commons.mail.EmailException;
|
||||||
import org.apache.commons.mail.HtmlEmail;
|
import org.apache.commons.mail.HtmlEmail;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
|
||||||
|
import javax.activation.CommandMap;
|
||||||
import javax.activation.DataSource;
|
import javax.activation.DataSource;
|
||||||
import javax.activation.FileDataSource;
|
import javax.activation.FileDataSource;
|
||||||
|
import javax.activation.MailcapCommandMap;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.mail.Session;
|
import javax.mail.Session;
|
||||||
@ -27,18 +30,19 @@ import static fr.xephi.authme.settings.properties.EmailSettings.MAIL_PASSWORD;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Xephi59
|
* Sends emails to players on behalf of the server.
|
||||||
*/
|
*/
|
||||||
public class SendMailSSL {
|
public class SendMailSSL {
|
||||||
|
|
||||||
@Inject
|
private final File dataFolder;
|
||||||
private AuthMe plugin;
|
private final String serverName;
|
||||||
@Inject
|
private final Settings settings;
|
||||||
private Settings settings;
|
|
||||||
@Inject
|
|
||||||
private BukkitService bukkitService;
|
|
||||||
|
|
||||||
SendMailSSL() {
|
@Inject
|
||||||
|
SendMailSSL(@DataFolder File dataFolder, Server server, Settings settings) {
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
this.serverName = server.getServerName();
|
||||||
|
this.settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,62 +61,57 @@ public class SendMailSSL {
|
|||||||
* @param name the name of the player
|
* @param name the name of the player
|
||||||
* @param mailAddress the player's email
|
* @param mailAddress the player's email
|
||||||
* @param newPass the new password
|
* @param newPass the new password
|
||||||
|
* @return true if email could be sent, false otherwise
|
||||||
*/
|
*/
|
||||||
public void sendPasswordMail(String name, String mailAddress, String newPass) {
|
public boolean sendPasswordMail(String name, String mailAddress, String newPass) {
|
||||||
if (!hasAllInformation()) {
|
if (!hasAllInformation()) {
|
||||||
ConsoleLogger.warning("Cannot perform email registration: not all email settings are complete");
|
ConsoleLogger.warning("Cannot perform email registration: not all email settings are complete");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String mailText = replaceTagsForPasswordMail(settings.getPasswordEmailMessage(), name, newPass);
|
HtmlEmail email;
|
||||||
bukkitService.runTaskAsynchronously(new Runnable() {
|
try {
|
||||||
|
email = initializeMail(mailAddress);
|
||||||
|
} catch (EmailException e) {
|
||||||
|
ConsoleLogger.logException("Failed to create email with the given settings:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
String mailText = replaceTagsForPasswordMail(settings.getPasswordEmailMessage(), name, newPass);
|
||||||
public void run() {
|
// Generate an image?
|
||||||
HtmlEmail email;
|
File file = null;
|
||||||
try {
|
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
||||||
email = initializeMail(mailAddress);
|
try {
|
||||||
} catch (EmailException e) {
|
file = generateImage(name, newPass);
|
||||||
ConsoleLogger.logException("Failed to create email with the given settings:", e);
|
mailText = embedImageIntoEmailContent(file, email, mailText);
|
||||||
return;
|
} catch (IOException | EmailException e) {
|
||||||
}
|
ConsoleLogger.logException(
|
||||||
|
"Unable to send new password as image for email " + mailAddress + ":", e);
|
||||||
String content = mailText;
|
|
||||||
// Generate an image?
|
|
||||||
File file = null;
|
|
||||||
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
|
||||||
try {
|
|
||||||
file = generateImage(name, plugin, newPass);
|
|
||||||
content = embedImageIntoEmailContent(file, email, content);
|
|
||||||
} catch (IOException | EmailException e) {
|
|
||||||
ConsoleLogger.logException(
|
|
||||||
"Unable to send new password as image for email " + mailAddress + ":", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendEmail(content, email);
|
|
||||||
FileUtils.delete(file);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
boolean couldSendEmail = sendEmail(mailText, email);
|
||||||
|
FileUtils.delete(file);
|
||||||
|
return couldSendEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendRecoveryCode(String name, String email, String code) {
|
public boolean sendRecoveryCode(String name, String email, String code) {
|
||||||
String message = replaceTagsForRecoveryCodeMail(settings.getRecoveryCodeEmailMessage(),
|
|
||||||
name, code, settings.getProperty(SecuritySettings.RECOVERY_CODE_HOURS_VALID));
|
|
||||||
|
|
||||||
HtmlEmail htmlEmail;
|
HtmlEmail htmlEmail;
|
||||||
try {
|
try {
|
||||||
htmlEmail = initializeMail(email);
|
htmlEmail = initializeMail(email);
|
||||||
} catch (EmailException e) {
|
} catch (EmailException e) {
|
||||||
ConsoleLogger.logException("Failed to create email for recovery code:", e);
|
ConsoleLogger.logException("Failed to create email for recovery code:", e);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
sendEmail(message, htmlEmail);
|
|
||||||
|
String message = replaceTagsForRecoveryCodeMail(settings.getRecoveryCodeEmailMessage(),
|
||||||
|
name, code, settings.getProperty(SecuritySettings.RECOVERY_CODE_HOURS_VALID));
|
||||||
|
return sendEmail(message, htmlEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File generateImage(String name, AuthMe plugin, String newPass) throws IOException {
|
private File generateImage(String name, String newPass) throws IOException {
|
||||||
ImageGenerator gen = new ImageGenerator(newPass);
|
ImageGenerator gen = new ImageGenerator(newPass);
|
||||||
File file = new File(plugin.getDataFolder(), name + "_new_pass.jpg");
|
File file = new File(dataFolder, name + "_new_pass.jpg");
|
||||||
ImageIO.write(gen.generateImage(), "jpg", file);
|
ImageIO.write(gen.generateImage(), "jpg", file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@ -124,7 +123,8 @@ public class SendMailSSL {
|
|||||||
return content.replace("<image />", "<img src=\"cid:" + tag + "\">");
|
return content.replace("<image />", "<img src=\"cid:" + tag + "\">");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HtmlEmail initializeMail(String emailAddress) throws EmailException {
|
@VisibleForTesting
|
||||||
|
HtmlEmail initializeMail(String emailAddress) throws EmailException {
|
||||||
String senderMail = settings.getProperty(EmailSettings.MAIL_ACCOUNT);
|
String senderMail = settings.getProperty(EmailSettings.MAIL_ACCOUNT);
|
||||||
String senderName = StringUtils.isEmpty(settings.getProperty(EmailSettings.MAIL_SENDER_NAME))
|
String senderName = StringUtils.isEmpty(settings.getProperty(EmailSettings.MAIL_SENDER_NAME))
|
||||||
? senderMail
|
? senderMail
|
||||||
@ -145,8 +145,18 @@ public class SendMailSSL {
|
|||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean sendEmail(String content, HtmlEmail email) {
|
@VisibleForTesting
|
||||||
|
boolean sendEmail(String content, HtmlEmail email) {
|
||||||
Thread.currentThread().setContextClassLoader(SendMailSSL.class.getClassLoader());
|
Thread.currentThread().setContextClassLoader(SendMailSSL.class.getClassLoader());
|
||||||
|
// Issue #999: Prevent UnsupportedDataTypeException: no object DCH for MIME type multipart/alternative
|
||||||
|
// cf. http://stackoverflow.com/questions/21856211/unsupporteddatatypeexception-no-object-dch-for-mime-type
|
||||||
|
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
|
||||||
|
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
|
||||||
|
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
|
||||||
|
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
|
||||||
|
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
|
||||||
|
mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
email.setHtmlMsg(content);
|
email.setHtmlMsg(content);
|
||||||
email.setTextMsg(content);
|
email.setTextMsg(content);
|
||||||
@ -166,14 +176,14 @@ public class SendMailSSL {
|
|||||||
private String replaceTagsForPasswordMail(String mailText, String name, String newPass) {
|
private String replaceTagsForPasswordMail(String mailText, String name, String newPass) {
|
||||||
return mailText
|
return mailText
|
||||||
.replace("<playername />", name)
|
.replace("<playername />", name)
|
||||||
.replace("<servername />", plugin.getServer().getServerName())
|
.replace("<servername />", serverName)
|
||||||
.replace("<generatedpass />", newPass);
|
.replace("<generatedpass />", newPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String replaceTagsForRecoveryCodeMail(String mailText, String name, String code, int hoursValid) {
|
private String replaceTagsForRecoveryCodeMail(String mailText, String name, String code, int hoursValid) {
|
||||||
return mailText
|
return mailText
|
||||||
.replace("<playername />", name)
|
.replace("<playername />", name)
|
||||||
.replace("<servername />", plugin.getServer().getServerName())
|
.replace("<servername />", serverName)
|
||||||
.replace("<recoverycode />", code)
|
.replace("<recoverycode />", code)
|
||||||
.replace("<hoursvalid />", String.valueOf(hoursValid));
|
.replace("<hoursvalid />", String.valueOf(hoursValid));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,7 @@ public class MessageFileHandler {
|
|||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
ConsoleLogger.warning("Error getting message with key '" + key + "'. "
|
ConsoleLogger.warning("Error getting message with key '" + key + "'. "
|
||||||
+ "Please verify your config file at '" + filename + "'");
|
+ "Please update your config file '" + filename + "' (or run /authme messages)");
|
||||||
return getDefault(key);
|
return getDefault(key);
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
|
|||||||
@ -5,156 +5,235 @@ package fr.xephi.authme.message;
|
|||||||
*/
|
*/
|
||||||
public enum MessageKey {
|
public enum MessageKey {
|
||||||
|
|
||||||
|
/** In order to use this command you must be authenticated! */
|
||||||
DENIED_COMMAND("denied_command"),
|
DENIED_COMMAND("denied_command"),
|
||||||
|
|
||||||
|
/** A player with the same IP is already in game! */
|
||||||
SAME_IP_ONLINE("same_ip_online"),
|
SAME_IP_ONLINE("same_ip_online"),
|
||||||
|
|
||||||
|
/** In order to chat you must be authenticated! */
|
||||||
DENIED_CHAT("denied_chat"),
|
DENIED_CHAT("denied_chat"),
|
||||||
|
|
||||||
|
/** AntiBot protection mode is enabled! You have to wait some minutes before joining the server. */
|
||||||
KICK_ANTIBOT("kick_antibot"),
|
KICK_ANTIBOT("kick_antibot"),
|
||||||
|
|
||||||
|
/** Can't find the requested user in the database! */
|
||||||
UNKNOWN_USER("unknown_user"),
|
UNKNOWN_USER("unknown_user"),
|
||||||
|
|
||||||
|
/** Your quit location was unsafe, you have been teleported to the world's spawnpoint. */
|
||||||
UNSAFE_QUIT_LOCATION("unsafe_spawn"),
|
UNSAFE_QUIT_LOCATION("unsafe_spawn"),
|
||||||
|
|
||||||
|
/** You're not logged in! */
|
||||||
NOT_LOGGED_IN("not_logged_in"),
|
NOT_LOGGED_IN("not_logged_in"),
|
||||||
|
|
||||||
|
/** You can register yourself to the server with the command "/register >password> >ConfirmPassword>" */
|
||||||
REGISTER_VOLUNTARILY("reg_voluntarily"),
|
REGISTER_VOLUNTARILY("reg_voluntarily"),
|
||||||
|
|
||||||
|
/** Usage: /login >password> */
|
||||||
USAGE_LOGIN("usage_log"),
|
USAGE_LOGIN("usage_log"),
|
||||||
|
|
||||||
|
/** Wrong password! */
|
||||||
WRONG_PASSWORD("wrong_pwd"),
|
WRONG_PASSWORD("wrong_pwd"),
|
||||||
|
|
||||||
|
/** Successfully unregistered! */
|
||||||
UNREGISTERED_SUCCESS("unregistered"),
|
UNREGISTERED_SUCCESS("unregistered"),
|
||||||
|
|
||||||
|
/** In-game registration is disabled! */
|
||||||
REGISTRATION_DISABLED("reg_disabled"),
|
REGISTRATION_DISABLED("reg_disabled"),
|
||||||
|
|
||||||
|
/** Logged-in due to Session Reconnection. */
|
||||||
SESSION_RECONNECTION("valid_session"),
|
SESSION_RECONNECTION("valid_session"),
|
||||||
|
|
||||||
|
/** Successful login! */
|
||||||
LOGIN_SUCCESS("login"),
|
LOGIN_SUCCESS("login"),
|
||||||
|
|
||||||
|
/** Your account isn't activated yet, please check your emails! */
|
||||||
ACCOUNT_NOT_ACTIVATED("vb_nonActiv"),
|
ACCOUNT_NOT_ACTIVATED("vb_nonActiv"),
|
||||||
|
|
||||||
|
/** You already have registered this username! */
|
||||||
NAME_ALREADY_REGISTERED("user_regged"),
|
NAME_ALREADY_REGISTERED("user_regged"),
|
||||||
|
|
||||||
|
/** You don't have the permission to perform this action! */
|
||||||
NO_PERMISSION("no_perm"),
|
NO_PERMISSION("no_perm"),
|
||||||
|
|
||||||
|
/** An unexpected error occurred, please contact an administrator! */
|
||||||
ERROR("error"),
|
ERROR("error"),
|
||||||
|
|
||||||
|
/** Please, login with the command "/login >password>" */
|
||||||
LOGIN_MESSAGE("login_msg"),
|
LOGIN_MESSAGE("login_msg"),
|
||||||
|
|
||||||
|
/** Please, register to the server with the command "/register >password> >ConfirmPassword>" */
|
||||||
REGISTER_MESSAGE("reg_msg"),
|
REGISTER_MESSAGE("reg_msg"),
|
||||||
|
|
||||||
|
/** Please, register to the server with the command "/register >email> >confirmEmail>" */
|
||||||
REGISTER_EMAIL_MESSAGE("reg_email_msg"),
|
REGISTER_EMAIL_MESSAGE("reg_email_msg"),
|
||||||
|
|
||||||
|
/** You have exceeded the maximum number of registrations (%reg_count/%max_acc %reg_names) for your connection! */
|
||||||
MAX_REGISTER_EXCEEDED("max_reg", "%max_acc", "%reg_count", "%reg_names"),
|
MAX_REGISTER_EXCEEDED("max_reg", "%max_acc", "%reg_count", "%reg_names"),
|
||||||
|
|
||||||
|
/** Usage: /register >password> >ConfirmPassword> */
|
||||||
USAGE_REGISTER("usage_reg"),
|
USAGE_REGISTER("usage_reg"),
|
||||||
|
|
||||||
|
/** Usage: /unregister >password> */
|
||||||
USAGE_UNREGISTER("usage_unreg"),
|
USAGE_UNREGISTER("usage_unreg"),
|
||||||
|
|
||||||
|
/** Password changed successfully! */
|
||||||
PASSWORD_CHANGED_SUCCESS("pwd_changed"),
|
PASSWORD_CHANGED_SUCCESS("pwd_changed"),
|
||||||
|
|
||||||
|
/** This user isn't registered! */
|
||||||
USER_NOT_REGISTERED("user_unknown"),
|
USER_NOT_REGISTERED("user_unknown"),
|
||||||
|
|
||||||
|
/** Passwords didn't match, check them again! */
|
||||||
PASSWORD_MATCH_ERROR("password_error"),
|
PASSWORD_MATCH_ERROR("password_error"),
|
||||||
|
|
||||||
|
/** You can't use your name as password, please choose another one... */
|
||||||
PASSWORD_IS_USERNAME_ERROR("password_error_nick"),
|
PASSWORD_IS_USERNAME_ERROR("password_error_nick"),
|
||||||
|
|
||||||
|
/** The chosen password isn't safe, please choose another one... */
|
||||||
PASSWORD_UNSAFE_ERROR("password_error_unsafe"),
|
PASSWORD_UNSAFE_ERROR("password_error_unsafe"),
|
||||||
|
|
||||||
|
/** Your password contains illegal characters. Allowed chars: REG_EX */
|
||||||
PASSWORD_CHARACTERS_ERROR("password_error_chars", "REG_EX"),
|
PASSWORD_CHARACTERS_ERROR("password_error_chars", "REG_EX"),
|
||||||
|
|
||||||
|
/** Your IP has been changed and your session data has expired! */
|
||||||
SESSION_EXPIRED("invalid_session"),
|
SESSION_EXPIRED("invalid_session"),
|
||||||
|
|
||||||
|
/** Only registered users can join the server! Please visit http://example.com to register yourself! */
|
||||||
MUST_REGISTER_MESSAGE("reg_only"),
|
MUST_REGISTER_MESSAGE("reg_only"),
|
||||||
|
|
||||||
|
/** You're already logged in! */
|
||||||
ALREADY_LOGGED_IN_ERROR("logged_in"),
|
ALREADY_LOGGED_IN_ERROR("logged_in"),
|
||||||
|
|
||||||
|
/** Logged-out successfully! */
|
||||||
LOGOUT_SUCCESS("logout"),
|
LOGOUT_SUCCESS("logout"),
|
||||||
|
|
||||||
|
/** The same username is already playing on the server! */
|
||||||
USERNAME_ALREADY_ONLINE_ERROR("same_nick"),
|
USERNAME_ALREADY_ONLINE_ERROR("same_nick"),
|
||||||
|
|
||||||
|
/** Successfully registered! */
|
||||||
REGISTER_SUCCESS("registered"),
|
REGISTER_SUCCESS("registered"),
|
||||||
|
|
||||||
|
/** Your password is too short or too long! Please try with another one! */
|
||||||
INVALID_PASSWORD_LENGTH("pass_len"),
|
INVALID_PASSWORD_LENGTH("pass_len"),
|
||||||
|
|
||||||
|
/** Configuration and database have been reloaded correctly! */
|
||||||
CONFIG_RELOAD_SUCCESS("reload"),
|
CONFIG_RELOAD_SUCCESS("reload"),
|
||||||
|
|
||||||
|
/** Login timeout exceeded, you have been kicked from the server, please try again! */
|
||||||
LOGIN_TIMEOUT_ERROR("timeout"),
|
LOGIN_TIMEOUT_ERROR("timeout"),
|
||||||
|
|
||||||
|
/** Usage: /changepassword >oldPassword> >newPassword> */
|
||||||
USAGE_CHANGE_PASSWORD("usage_changepassword"),
|
USAGE_CHANGE_PASSWORD("usage_changepassword"),
|
||||||
|
|
||||||
|
/** Your username is either too short or too long! */
|
||||||
INVALID_NAME_LENGTH("name_len"),
|
INVALID_NAME_LENGTH("name_len"),
|
||||||
|
|
||||||
|
/** Your username contains illegal characters. Allowed chars: REG_EX */
|
||||||
INVALID_NAME_CHARACTERS("regex", "REG_EX"),
|
INVALID_NAME_CHARACTERS("regex", "REG_EX"),
|
||||||
|
|
||||||
|
/** Please add your email to your account with the command "/email add >yourEmail> >confirmEmail>" */
|
||||||
ADD_EMAIL_MESSAGE("add_email"),
|
ADD_EMAIL_MESSAGE("add_email"),
|
||||||
|
|
||||||
|
/** Forgot your password? Please use the command "/email recovery >yourEmail>" */
|
||||||
FORGOT_PASSWORD_MESSAGE("recovery_email"),
|
FORGOT_PASSWORD_MESSAGE("recovery_email"),
|
||||||
|
|
||||||
|
/** To login you have to solve a captcha code, please use the command "/captcha >theCaptcha>" */
|
||||||
USAGE_CAPTCHA("usage_captcha", "<theCaptcha>"),
|
USAGE_CAPTCHA("usage_captcha", "<theCaptcha>"),
|
||||||
|
|
||||||
|
/** Wrong captcha, please type "/captcha THE_CAPTCHA" into the chat! */
|
||||||
CAPTCHA_WRONG_ERROR("wrong_captcha", "THE_CAPTCHA"),
|
CAPTCHA_WRONG_ERROR("wrong_captcha", "THE_CAPTCHA"),
|
||||||
|
|
||||||
|
/** Captcha code solved correctly! */
|
||||||
CAPTCHA_SUCCESS("valid_captcha"),
|
CAPTCHA_SUCCESS("valid_captcha"),
|
||||||
|
|
||||||
|
/** A VIP player has joined the server when it was full! */
|
||||||
KICK_FOR_VIP("kick_forvip"),
|
KICK_FOR_VIP("kick_forvip"),
|
||||||
|
|
||||||
|
/** The server is full, try again later! */
|
||||||
KICK_FULL_SERVER("kick_fullserver"),
|
KICK_FULL_SERVER("kick_fullserver"),
|
||||||
|
|
||||||
|
/** Usage: /email add >email> >confirmEmail> */
|
||||||
USAGE_ADD_EMAIL("usage_email_add"),
|
USAGE_ADD_EMAIL("usage_email_add"),
|
||||||
|
|
||||||
|
/** Usage: /email change >oldEmail> >newEmail> */
|
||||||
USAGE_CHANGE_EMAIL("usage_email_change"),
|
USAGE_CHANGE_EMAIL("usage_email_change"),
|
||||||
|
|
||||||
|
/** Usage: /email recovery >Email> */
|
||||||
USAGE_RECOVER_EMAIL("usage_email_recovery"),
|
USAGE_RECOVER_EMAIL("usage_email_recovery"),
|
||||||
|
|
||||||
|
/** Invalid new email, try again! */
|
||||||
INVALID_NEW_EMAIL("new_email_invalid"),
|
INVALID_NEW_EMAIL("new_email_invalid"),
|
||||||
|
|
||||||
|
/** Invalid old email, try again! */
|
||||||
INVALID_OLD_EMAIL("old_email_invalid"),
|
INVALID_OLD_EMAIL("old_email_invalid"),
|
||||||
|
|
||||||
|
/** Invalid email address, try again! */
|
||||||
INVALID_EMAIL("email_invalid"),
|
INVALID_EMAIL("email_invalid"),
|
||||||
|
|
||||||
|
/** Email address successfully added to your account! */
|
||||||
EMAIL_ADDED_SUCCESS("email_added"),
|
EMAIL_ADDED_SUCCESS("email_added"),
|
||||||
|
|
||||||
|
/** Please confirm your email address! */
|
||||||
CONFIRM_EMAIL_MESSAGE("email_confirm"),
|
CONFIRM_EMAIL_MESSAGE("email_confirm"),
|
||||||
|
|
||||||
|
/** Email address changed correctly! */
|
||||||
EMAIL_CHANGED_SUCCESS("email_changed"),
|
EMAIL_CHANGED_SUCCESS("email_changed"),
|
||||||
|
|
||||||
|
/** Your current email address is: %email */
|
||||||
EMAIL_SHOW("email_show", "%email"),
|
EMAIL_SHOW("email_show", "%email"),
|
||||||
|
|
||||||
|
/** You currently don't have email address associated with this account. */
|
||||||
SHOW_NO_EMAIL("show_no_email"),
|
SHOW_NO_EMAIL("show_no_email"),
|
||||||
|
|
||||||
|
/** Recovery email sent successfully! Please check your email inbox! */
|
||||||
RECOVERY_EMAIL_SENT_MESSAGE("email_send"),
|
RECOVERY_EMAIL_SENT_MESSAGE("email_send"),
|
||||||
|
|
||||||
|
/** A recovery email was already sent! You can discard it and send a new one using the command below: */
|
||||||
RECOVERY_EMAIL_ALREADY_SENT_MESSAGE("email_exists"),
|
RECOVERY_EMAIL_ALREADY_SENT_MESSAGE("email_exists"),
|
||||||
|
|
||||||
|
/** Your country is banned from this server! */
|
||||||
COUNTRY_BANNED_ERROR("country_banned"),
|
COUNTRY_BANNED_ERROR("country_banned"),
|
||||||
|
|
||||||
|
/** [AntiBotService] AntiBot enabled due to the huge number of connections! */
|
||||||
ANTIBOT_AUTO_ENABLED_MESSAGE("antibot_auto_enabled"),
|
ANTIBOT_AUTO_ENABLED_MESSAGE("antibot_auto_enabled"),
|
||||||
|
|
||||||
|
/** [AntiBotService] AntiBot disabled after %m minutes! */
|
||||||
ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled", "%m"),
|
ANTIBOT_AUTO_DISABLED_MESSAGE("antibot_auto_disabled", "%m"),
|
||||||
|
|
||||||
|
/** The email address is already being used */
|
||||||
EMAIL_ALREADY_USED_ERROR("email_already_used"),
|
EMAIL_ALREADY_USED_ERROR("email_already_used"),
|
||||||
|
|
||||||
|
/** Your secret code is %code. You can scan it from here %url */
|
||||||
TWO_FACTOR_CREATE("two_factor_create", "%code", "%url"),
|
TWO_FACTOR_CREATE("two_factor_create", "%code", "%url"),
|
||||||
|
|
||||||
|
/** You are not the owner of this account. Please choose another name! */
|
||||||
NOT_OWNER_ERROR("not_owner_error"),
|
NOT_OWNER_ERROR("not_owner_error"),
|
||||||
|
|
||||||
|
/** You should join using username %valid, not %invalid. */
|
||||||
INVALID_NAME_CASE("invalid_name_case", "%valid", "%invalid"),
|
INVALID_NAME_CASE("invalid_name_case", "%valid", "%invalid"),
|
||||||
|
|
||||||
|
/** You have been temporarily banned for failing to log in too many times. */
|
||||||
TEMPBAN_MAX_LOGINS("tempban_max_logins"),
|
TEMPBAN_MAX_LOGINS("tempban_max_logins"),
|
||||||
|
|
||||||
|
/** You own %count accounts: */
|
||||||
ACCOUNTS_OWNED_SELF("accounts_owned_self", "%count"),
|
ACCOUNTS_OWNED_SELF("accounts_owned_self", "%count"),
|
||||||
|
|
||||||
|
/** The player %name has %count accounts: */
|
||||||
ACCOUNTS_OWNED_OTHER("accounts_owned_other", "%name", "%count"),
|
ACCOUNTS_OWNED_OTHER("accounts_owned_other", "%name", "%count"),
|
||||||
|
|
||||||
|
/** An admin just registered you; please log in again */
|
||||||
KICK_FOR_ADMIN_REGISTER("kicked_admin_registered"),
|
KICK_FOR_ADMIN_REGISTER("kicked_admin_registered"),
|
||||||
|
|
||||||
|
/** Error: not all required settings are set for sending emails. Please contact an admin. */
|
||||||
INCOMPLETE_EMAIL_SETTINGS("incomplete_email_settings"),
|
INCOMPLETE_EMAIL_SETTINGS("incomplete_email_settings"),
|
||||||
|
|
||||||
|
/** The email could not be sent. Please contact an administrator. */
|
||||||
|
EMAIL_SEND_FAILURE("email_send_failure"),
|
||||||
|
|
||||||
|
/** A recovery code to reset your password has been sent to your email. */
|
||||||
RECOVERY_CODE_SENT("recovery_code_sent"),
|
RECOVERY_CODE_SENT("recovery_code_sent"),
|
||||||
|
|
||||||
|
/** The recovery code is not correct! Use /email recovery [email] to generate a new one */
|
||||||
INCORRECT_RECOVERY_CODE("recovery_code_incorrect");
|
INCORRECT_RECOVERY_CODE("recovery_code_incorrect");
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|||||||
@ -12,14 +12,9 @@ import org.apache.logging.log4j.message.Message;
|
|||||||
*
|
*
|
||||||
* @author Xephi59
|
* @author Xephi59
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class Log4JFilter extends AbstractFilter {
|
public class Log4JFilter extends AbstractFilter {
|
||||||
|
|
||||||
/**
|
private static final long serialVersionUID = -5594073755007974254L;
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public Log4JFilter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates a Message instance and returns the {@link Result} value
|
* Validates a Message instance and returns the {@link Result} value
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import fr.xephi.authme.settings.properties.PluginSettings;
|
|||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ public class AuthGroupHandler implements Reloadable {
|
|||||||
private String unregisteredGroup;
|
private String unregisteredGroup;
|
||||||
private String registeredGroup;
|
private String registeredGroup;
|
||||||
|
|
||||||
AuthGroupHandler() { }
|
AuthGroupHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the group of a player, by its AuthMe group type.
|
* Set the group of a player, by its AuthMe group type.
|
||||||
@ -114,6 +116,7 @@ public class AuthGroupHandler implements Reloadable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@PostConstruct
|
||||||
public void reload() {
|
public void reload() {
|
||||||
unloggedInGroup = settings.getProperty(SecuritySettings.UNLOGGEDIN_GROUP);
|
unloggedInGroup = settings.getProperty(SecuritySettings.UNLOGGEDIN_GROUP);
|
||||||
unregisteredGroup = settings.getProperty(HooksSettings.UNREGISTERED_GROUP);
|
unregisteredGroup = settings.getProperty(HooksSettings.UNREGISTERED_GROUP);
|
||||||
|
|||||||
@ -78,12 +78,12 @@ public class PermissionsManager implements Reloadable {
|
|||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
// Show a success message and return
|
// Show a success message and return
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
ConsoleLogger.info("Hooked into " + type.getName() + "!");
|
ConsoleLogger.info("Hooked into " + type.getDisplayName() + "!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// An error occurred, show a warning message
|
// An error occurred, show a warning message
|
||||||
ConsoleLogger.logException("Error while hooking into " + type.getName(), ex);
|
ConsoleLogger.logException("Error while hooking into " + type.getDisplayName(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ public class PermissionsManager implements Reloadable {
|
|||||||
|
|
||||||
// Make sure the plugin is enabled before hooking
|
// Make sure the plugin is enabled before hooking
|
||||||
if (!plugin.isEnabled()) {
|
if (!plugin.isEnabled()) {
|
||||||
ConsoleLogger.info("Not hooking into " + type.getName() + " because it's disabled!");
|
ConsoleLogger.info("Not hooking into " + type.getDisplayName() + " because it's disabled!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +414,7 @@ public class PermissionsManager implements Reloadable {
|
|||||||
*/
|
*/
|
||||||
public boolean setGroups(Player player, List<String> groupNames) {
|
public boolean setGroups(Player player, List<String> groupNames) {
|
||||||
// If no permissions system is used or if there's no group supplied, return false
|
// If no permissions system is used or if there's no group supplied, return false
|
||||||
if (!isEnabled() || groupNames.size() <= 0)
|
if (!isEnabled() || groupNames.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set the main group
|
// Set the main group
|
||||||
|
|||||||
@ -33,21 +33,21 @@ public enum PermissionsSystemType {
|
|||||||
/**
|
/**
|
||||||
* The display name of the permissions system.
|
* The display name of the permissions system.
|
||||||
*/
|
*/
|
||||||
public String name;
|
private String displayName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the permissions system plugin.
|
* The name of the permissions system plugin.
|
||||||
*/
|
*/
|
||||||
public String pluginName;
|
private String pluginName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for PermissionsSystemType.
|
* Constructor for PermissionsSystemType.
|
||||||
*
|
*
|
||||||
* @param name Display name of the permissions system.
|
* @param displayName Display name of the permissions system.
|
||||||
* @param pluginName Name of the plugin.
|
* @param pluginName Name of the plugin.
|
||||||
*/
|
*/
|
||||||
PermissionsSystemType(String name, String pluginName) {
|
PermissionsSystemType(String displayName, String pluginName) {
|
||||||
this.name = name;
|
this.displayName = displayName;
|
||||||
this.pluginName = pluginName;
|
this.pluginName = pluginName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ public enum PermissionsSystemType {
|
|||||||
*
|
*
|
||||||
* @return Display name.
|
* @return Display name.
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getDisplayName() {
|
||||||
return this.name;
|
return this.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +76,7 @@ public enum PermissionsSystemType {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getName();
|
return getDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -17,7 +17,7 @@ public enum PlayerStatePermission implements PermissionNode {
|
|||||||
BYPASS_FORCE_SURVIVAL("authme.bypassforcesurvival", DefaultPermission.OP_ONLY),
|
BYPASS_FORCE_SURVIVAL("authme.bypassforcesurvival", DefaultPermission.OP_ONLY),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission node to identify VIP users.
|
* When the server is full and someone with this permission joins the server, someone will be kicked.
|
||||||
*/
|
*/
|
||||||
IS_VIP("authme.vip", DefaultPermission.OP_ONLY),
|
IS_VIP("authme.vip", DefaultPermission.OP_ONLY),
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ public class BPermissionsHandler implements PermissionHandler {
|
|||||||
List<String> groups = getGroups(player);
|
List<String> groups = getGroups(player);
|
||||||
|
|
||||||
// Make sure there is any group available, or return null
|
// Make sure there is any group available, or return null
|
||||||
if (groups.size() == 0)
|
if (groups.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Return the first group
|
// Return the first group
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public class PermissionsBukkitHandler implements PermissionHandler {
|
|||||||
List<String> groups = getGroups(player);
|
List<String> groups = getGroups(player);
|
||||||
|
|
||||||
// Make sure there is any group available, or return null
|
// Make sure there is any group available, or return null
|
||||||
if (groups.size() == 0)
|
if (groups.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Return the first group
|
// Return the first group
|
||||||
|
|||||||
@ -77,7 +77,7 @@ public class PermissionsExHandler implements PermissionHandler {
|
|||||||
PermissionUser user = permissionManager.getUser(player);
|
PermissionUser user = permissionManager.getUser(player);
|
||||||
|
|
||||||
List<String> groups = user.getParentIdentifiers(null);
|
List<String> groups = user.getParentIdentifiers(null);
|
||||||
if (groups.size() == 0)
|
if (groups.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return groups.get(0);
|
return groups.get(0);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -19,7 +19,7 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService processService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PasswordSecurity passwordSecurity;
|
private PasswordSecurity passwordSecurity;
|
||||||
@ -27,7 +27,8 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
AsyncChangePassword() { }
|
AsyncChangePassword() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void changePassword(final Player player, String oldPassword, String newPassword) {
|
public void changePassword(final Player player, String oldPassword, String newPassword) {
|
||||||
@ -38,15 +39,15 @@ public class AsyncChangePassword implements AsynchronousProcess {
|
|||||||
auth.setPassword(hashedPassword);
|
auth.setPassword(hashedPassword);
|
||||||
|
|
||||||
if (!dataSource.updatePassword(auth)) {
|
if (!dataSource.updatePassword(auth)) {
|
||||||
processService.send(player, MessageKey.ERROR);
|
commonService.send(player, MessageKey.ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerCache.updatePlayer(auth);
|
playerCache.updatePlayer(auth);
|
||||||
processService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
commonService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||||
ConsoleLogger.info(player.getName() + " changed his password");
|
ConsoleLogger.info(player.getName() + " changed his password");
|
||||||
} else {
|
} else {
|
||||||
processService.send(player, MessageKey.WRONG_PASSWORD);
|
commonService.send(player, MessageKey.WRONG_PASSWORD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ import javax.inject.Inject;
|
|||||||
public class AsyncAddEmail implements AsynchronousProcess {
|
public class AsyncAddEmail implements AsynchronousProcess {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
@ -26,6 +27,9 @@ public class AsyncAddEmail implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ValidationService validationService;
|
||||||
|
|
||||||
AsyncAddEmail() { }
|
AsyncAddEmail() { }
|
||||||
|
|
||||||
public void addEmail(Player player, String email) {
|
public void addEmail(Player player, String email) {
|
||||||
@ -37,9 +41,9 @@ public class AsyncAddEmail implements AsynchronousProcess {
|
|||||||
|
|
||||||
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
|
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
|
||||||
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
|
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
|
||||||
} else if (!service.validateEmail(email)) {
|
} else if (!validationService.validateEmail(email)) {
|
||||||
service.send(player, MessageKey.INVALID_EMAIL);
|
service.send(player, MessageKey.INVALID_EMAIL);
|
||||||
} else if (!service.isEmailFreeForRegistration(email, player)) {
|
} else if (!validationService.isEmailFreeForRegistration(email, player)) {
|
||||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||||
} else {
|
} else {
|
||||||
auth.setEmail(email);
|
auth.setEmail(email);
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ import javax.inject.Inject;
|
|||||||
public class AsyncChangeEmail implements AsynchronousProcess {
|
public class AsyncChangeEmail implements AsynchronousProcess {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -25,6 +26,9 @@ public class AsyncChangeEmail implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ValidationService validationService;
|
||||||
|
|
||||||
AsyncChangeEmail() { }
|
AsyncChangeEmail() { }
|
||||||
|
|
||||||
public void changeEmail(Player player, String oldEmail, String newEmail) {
|
public void changeEmail(Player player, String oldEmail, String newEmail) {
|
||||||
@ -35,11 +39,11 @@ public class AsyncChangeEmail implements AsynchronousProcess {
|
|||||||
|
|
||||||
if (currentEmail == null) {
|
if (currentEmail == null) {
|
||||||
service.send(player, MessageKey.USAGE_ADD_EMAIL);
|
service.send(player, MessageKey.USAGE_ADD_EMAIL);
|
||||||
} else if (newEmail == null || !service.validateEmail(newEmail)) {
|
} else if (newEmail == null || !validationService.validateEmail(newEmail)) {
|
||||||
service.send(player, MessageKey.INVALID_NEW_EMAIL);
|
service.send(player, MessageKey.INVALID_NEW_EMAIL);
|
||||||
} else if (!oldEmail.equals(currentEmail)) {
|
} else if (!oldEmail.equals(currentEmail)) {
|
||||||
service.send(player, MessageKey.INVALID_OLD_EMAIL);
|
service.send(player, MessageKey.INVALID_OLD_EMAIL);
|
||||||
} else if (!service.isEmailFreeForRegistration(newEmail, player)) {
|
} else if (!validationService.isEmailFreeForRegistration(newEmail, player)) {
|
||||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||||
} else {
|
} else {
|
||||||
saveNewEmail(auth, player, newEmail);
|
saveNewEmail(auth, player, newEmail);
|
||||||
|
|||||||
@ -13,8 +13,9 @@ import fr.xephi.authme.message.MessageKey;
|
|||||||
import fr.xephi.authme.permission.AuthGroupType;
|
import fr.xephi.authme.permission.AuthGroupType;
|
||||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||||
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
@ -22,9 +23,7 @@ import fr.xephi.authme.settings.properties.RestrictionSettings;
|
|||||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.apache.commons.lang.reflect.MethodUtils;
|
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
@ -39,9 +38,6 @@ import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
|||||||
*/
|
*/
|
||||||
public class AsynchronousJoin implements AsynchronousProcess {
|
public class AsynchronousJoin implements AsynchronousProcess {
|
||||||
|
|
||||||
private static final boolean DISABLE_COLLISIONS = MethodUtils
|
|
||||||
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private AuthMe plugin;
|
private AuthMe plugin;
|
||||||
|
|
||||||
@ -49,7 +45,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
private DataSource database;
|
private DataSource database;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@ -72,23 +68,20 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private AsynchronousLogin asynchronousLogin;
|
private AsynchronousLogin asynchronousLogin;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private CommandManager commandManager;
|
||||||
|
|
||||||
AsynchronousJoin() {
|
AsynchronousJoin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void processJoin(final Player player) {
|
public void processJoin(final Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
final String ip = PlayerUtils.getPlayerIp(player);
|
final String ip = PlayerUtils.getPlayerIp(player);
|
||||||
|
|
||||||
if (isPlayerUnrestricted(name)) {
|
if (service.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent player collisions in 1.9
|
|
||||||
if (DISABLE_COLLISIONS) {
|
|
||||||
player.setCollidable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
|
if (service.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
|
||||||
&& !service.hasPermission(player, PlayerStatePermission.BYPASS_FORCE_SURVIVAL)) {
|
&& !service.hasPermission(player, PlayerStatePermission.BYPASS_FORCE_SURVIVAL)) {
|
||||||
bukkitService.runTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
bukkitService.runTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
||||||
@ -115,7 +108,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final boolean isAuthAvailable = database.isAuthAvailable(name);
|
final boolean isAuthAvailable = database.isAuthAvailable(name);
|
||||||
|
|
||||||
if (isAuthAvailable) {
|
if (isAuthAvailable) {
|
||||||
@ -162,26 +154,23 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
|
|
||||||
final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||||
|
|
||||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() {
|
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||||
@Override
|
player.setOp(false);
|
||||||
public void run() {
|
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
|
||||||
player.setOp(false);
|
&& service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
|
||||||
if (!service.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)
|
player.setFlySpeed(0.0f);
|
||||||
&& service.getProperty(RestrictionSettings.REMOVE_SPEED)) {
|
player.setWalkSpeed(0.0f);
|
||||||
player.setFlySpeed(0.0f);
|
|
||||||
player.setWalkSpeed(0.0f);
|
|
||||||
}
|
|
||||||
player.setNoDamageTicks(registrationTimeout);
|
|
||||||
if (pluginHookService.isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
|
|
||||||
player.performCommand("motd");
|
|
||||||
}
|
|
||||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
|
||||||
// Allow infinite blindness effect
|
|
||||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
player.setNoDamageTicks(registrationTimeout);
|
||||||
|
if (pluginHookService.isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
|
||||||
|
player.performCommand("motd");
|
||||||
|
}
|
||||||
|
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||||
|
// Allow infinite blindness effect
|
||||||
|
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||||
|
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
||||||
|
}
|
||||||
|
commandManager.runCommandsOnJoin(player);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Timeout and message task
|
// Timeout and message task
|
||||||
@ -189,10 +178,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
limboPlayerTaskManager.registerMessageTask(name, isAuthAvailable);
|
limboPlayerTaskManager.registerMessageTask(name, isAuthAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPlayerUnrestricted(String name) {
|
|
||||||
return service.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the name is restricted based on the restriction settings.
|
* Returns whether the name is restricted based on the restriction settings.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import fr.xephi.authme.permission.PermissionsManager;
|
|||||||
import fr.xephi.authme.permission.PlayerPermission;
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SyncProcessManager;
|
import fr.xephi.authme.process.SyncProcessManager;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
@ -44,7 +44,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PermissionsManager permissionsManager;
|
private PermissionsManager permissionsManager;
|
||||||
@ -224,7 +224,11 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
player.setNoDamageTicks(0);
|
player.setNoDamageTicks(0);
|
||||||
|
|
||||||
service.send(player, MessageKey.LOGIN_SUCCESS);
|
service.send(player, MessageKey.LOGIN_SUCCESS);
|
||||||
displayOtherAccounts(auth, player);
|
|
||||||
|
// Other auths
|
||||||
|
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp());
|
||||||
|
runCommandOtherAccounts(auths, player, auth.getIp());
|
||||||
|
displayOtherAccounts(auths, player);
|
||||||
|
|
||||||
final String email = auth.getEmail();
|
final String email = auth.getEmail();
|
||||||
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
|
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
|
||||||
@ -252,12 +256,29 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayOtherAccounts(PlayerAuth auth, Player player) {
|
private void runCommandOtherAccounts(List<String> auths, Player player, String ip) {
|
||||||
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS) || auth == null) {
|
int threshold = service.getProperty(RestrictionSettings.OTHER_ACCOUNTS_CMD_THRESHOLD);
|
||||||
|
String command = service.getProperty(RestrictionSettings.OTHER_ACCOUNTS_CMD);
|
||||||
|
|
||||||
|
if(threshold < 2 || command.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auths.size() < threshold) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bukkitService.dispatchConsoleCommand(command
|
||||||
|
.replaceAll("%playername%", player.getName())
|
||||||
|
.replaceAll("%playerip%", ip)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayOtherAccounts(List<String> auths, Player player) {
|
||||||
|
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp());
|
|
||||||
if (auths.size() <= 1) {
|
if (auths.size() <= 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,38 +8,31 @@ import fr.xephi.authme.datasource.DataSource;
|
|||||||
import fr.xephi.authme.events.LoginEvent;
|
import fr.xephi.authme.events.LoginEvent;
|
||||||
import fr.xephi.authme.events.RestoreInventoryEvent;
|
import fr.xephi.authme.events.RestoreInventoryEvent;
|
||||||
import fr.xephi.authme.listener.PlayerListener;
|
import fr.xephi.authme.listener.PlayerListener;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
|
||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.service.BungeeService;
|
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.service.BungeeService;
|
||||||
import fr.xephi.authme.service.TeleportationService;
|
import fr.xephi.authme.service.TeleportationService;
|
||||||
import org.apache.commons.lang.reflect.MethodUtils;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
|
import fr.xephi.authme.util.StringUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static fr.xephi.authme.settings.properties.PluginSettings.KEEP_COLLISIONS_DISABLED;
|
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
||||||
|
|
||||||
public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||||
|
|
||||||
private static final boolean RESTORE_COLLISIONS = MethodUtils
|
|
||||||
.getAccessibleMethod(LivingEntity.class, "setCollidable", new Class[]{}) != null;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private AuthMe plugin;
|
private AuthMe plugin;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BungeeService bungeeService;
|
private BungeeService bungeeService;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ProcessService service;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboCache limboCache;
|
private LimboCache limboCache;
|
||||||
|
|
||||||
@ -55,6 +48,12 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private CommandManager commandManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
ProcessSyncPlayerLogin() {
|
ProcessSyncPlayerLogin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,16 +65,6 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forceCommands(Player player) {
|
|
||||||
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS)) {
|
|
||||||
player.performCommand(command.replace("%p", player.getName()));
|
|
||||||
}
|
|
||||||
for (String command : service.getProperty(RegistrationSettings.FORCE_COMMANDS_AS_CONSOLE)) {
|
|
||||||
Bukkit.getServer().dispatchCommand(
|
|
||||||
Bukkit.getServer().getConsoleSender(), command.replace("%p", player.getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void processPlayerLogin(Player player) {
|
public void processPlayerLogin(Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
|
|
||||||
@ -88,11 +77,7 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
// because LimboCache#restoreData teleport player to last location.
|
// because LimboCache#restoreData teleport player to last location.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RESTORE_COLLISIONS && !service.getProperty(KEEP_COLLISIONS_DISABLED)) {
|
if (settings.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||||
player.setCollidable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
|
||||||
restoreInventory(player);
|
restoreInventory(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,19 +85,16 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
teleportationService.teleportOnLogin(player, auth, limbo);
|
teleportationService.teleportOnLogin(player, auth, limbo);
|
||||||
|
|
||||||
// We can now display the join message (if delayed)
|
// We can now display the join message (if delayed)
|
||||||
String jm = PlayerListener.joinMessage.get(name);
|
String joinMessage = PlayerListener.joinMessage.remove(name);
|
||||||
if (jm != null) {
|
if (!StringUtils.isEmpty(joinMessage)) {
|
||||||
if (!jm.isEmpty()) {
|
for (Player p : bukkitService.getOnlinePlayers()) {
|
||||||
for (Player p : bukkitService.getOnlinePlayers()) {
|
if (p.isOnline()) {
|
||||||
if (p.isOnline()) {
|
p.sendMessage(joinMessage);
|
||||||
p.sendMessage(jm);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PlayerListener.joinMessage.remove(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
if (settings.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||||
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,20 +103,20 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
player.saveData();
|
player.saveData();
|
||||||
|
|
||||||
// Login is done, display welcome message
|
// Login is done, display welcome message
|
||||||
if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
|
if (settings.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
|
||||||
if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
|
if (settings.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
|
||||||
for (String s : service.getSettings().getWelcomeMessage()) {
|
for (String s : settings.getWelcomeMessage()) {
|
||||||
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
|
Bukkit.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (String s : service.getSettings().getWelcomeMessage()) {
|
for (String s : settings.getWelcomeMessage()) {
|
||||||
player.sendMessage(plugin.replaceAllInfo(s, player));
|
player.sendMessage(plugin.replaceAllInfo(s, player));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login is now finished; we can force all commands
|
// Login is now finished; we can force all commands
|
||||||
forceCommands(player);
|
commandManager.runCommandsOnLogin(player);
|
||||||
|
|
||||||
// Send Bungee stuff. The service will check if it is enabled or not.
|
// Send Bungee stuff. The service will check if it is enabled or not.
|
||||||
bungeeService.connectPlayer(player);
|
bungeeService.connectPlayer(player);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import fr.xephi.authme.data.limbo.LimboCache;
|
|||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SyncProcessManager;
|
import fr.xephi.authme.process.SyncProcessManager;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -19,7 +19,7 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
|||||||
private DataSource database;
|
private DataSource database;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import fr.xephi.authme.events.LogoutEvent;
|
|||||||
import fr.xephi.authme.listener.protocollib.ProtocolLibService;
|
import fr.xephi.authme.listener.protocollib.ProtocolLibService;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.permission.AuthGroupType;
|
import fr.xephi.authme.permission.AuthGroupType;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
@ -25,7 +25,7 @@ import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
|||||||
public class ProcessSynchronousPlayerLogout implements SynchronousProcess {
|
public class ProcessSynchronousPlayerLogout implements SynchronousProcess {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import fr.xephi.authme.data.auth.PlayerCache;
|
|||||||
import fr.xephi.authme.datasource.CacheDataSource;
|
import fr.xephi.authme.datasource.CacheDataSource;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SyncProcessManager;
|
import fr.xephi.authme.process.SyncProcessManager;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
@ -27,7 +27,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
|||||||
private DataSource database;
|
private DataSource database;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import fr.xephi.authme.mail.SendMailSSL;
|
|||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SyncProcessManager;
|
import fr.xephi.authme.process.SyncProcessManager;
|
||||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
@ -51,7 +51,7 @@ public class AsyncRegister implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private PasswordSecurity passwordSecurity;
|
private PasswordSecurity passwordSecurity;
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
@Inject
|
@Inject
|
||||||
private SyncProcessManager syncProcessManager;
|
private SyncProcessManager syncProcessManager;
|
||||||
@Inject
|
@Inject
|
||||||
@ -148,8 +148,12 @@ public class AsyncRegister implements AsynchronousProcess {
|
|||||||
}
|
}
|
||||||
database.updateEmail(auth);
|
database.updateEmail(auth);
|
||||||
database.updateSession(auth);
|
database.updateSession(auth);
|
||||||
sendMailSsl.sendPasswordMail(name, email, password);
|
boolean couldSendMail = sendMailSsl.sendPasswordMail(name, email, password);
|
||||||
syncProcessManager.processSyncEmailRegister(player);
|
if (couldSendMail) {
|
||||||
|
syncProcessManager.processSyncEmailRegister(player);
|
||||||
|
} else {
|
||||||
|
service.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void passwordRegister(final Player player, String password, boolean autoLogin) {
|
private void passwordRegister(final Player player, String password, boolean autoLogin) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package fr.xephi.authme.process.register;
|
|||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.permission.AuthGroupType;
|
import fr.xephi.authme.permission.AuthGroupType;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||||
@ -16,13 +16,13 @@ import javax.inject.Inject;
|
|||||||
public class ProcessSyncEmailRegister implements SynchronousProcess {
|
public class ProcessSyncEmailRegister implements SynchronousProcess {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboPlayerTaskManager limboPlayerTaskManager;
|
private LimboPlayerTaskManager limboPlayerTaskManager;
|
||||||
|
|
||||||
ProcessSyncEmailRegister() { }
|
ProcessSyncEmailRegister() {
|
||||||
|
}
|
||||||
|
|
||||||
public void processEmailRegister(Player player) {
|
public void processEmailRegister(Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
|
|||||||
@ -4,15 +4,15 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
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.permission.AuthGroupType;
|
import fr.xephi.authme.permission.AuthGroupType;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.service.BungeeService;
|
import fr.xephi.authme.service.BungeeService;
|
||||||
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
import fr.xephi.authme.task.LimboPlayerTaskManager;
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -25,7 +25,7 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
|||||||
private BungeeService bungeeService;
|
private BungeeService bungeeService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboCache limboCache;
|
private LimboCache limboCache;
|
||||||
@ -33,17 +33,10 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private LimboPlayerTaskManager limboPlayerTaskManager;
|
private LimboPlayerTaskManager limboPlayerTaskManager;
|
||||||
|
|
||||||
ProcessSyncPasswordRegister() {
|
@Inject
|
||||||
}
|
private CommandManager commandManager;
|
||||||
|
|
||||||
private void forceCommands(Player player) {
|
ProcessSyncPasswordRegister() {
|
||||||
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS)) {
|
|
||||||
player.performCommand(command.replace("%p", player.getName()));
|
|
||||||
}
|
|
||||||
for (String command : service.getProperty(RegistrationSettings.FORCE_REGISTER_COMMANDS_AS_CONSOLE)) {
|
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
|
|
||||||
command.replace("%p", player.getName()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +76,7 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register is now finished; we can force all commands
|
// Register is now finished; we can force all commands
|
||||||
forceCommands(player);
|
commandManager.runCommandsOnRegister(player);
|
||||||
|
|
||||||
// Request login after registration
|
// Request login after registration
|
||||||
if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
|
if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import fr.xephi.authme.message.MessageKey;
|
|||||||
import fr.xephi.authme.permission.AuthGroupHandler;
|
import fr.xephi.authme.permission.AuthGroupHandler;
|
||||||
import fr.xephi.authme.permission.AuthGroupType;
|
import fr.xephi.authme.permission.AuthGroupType;
|
||||||
import fr.xephi.authme.process.AsynchronousProcess;
|
import fr.xephi.authme.process.AsynchronousProcess;
|
||||||
import fr.xephi.authme.process.ProcessService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
import fr.xephi.authme.security.PasswordSecurity;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
@ -31,7 +31,7 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
|||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private CommonService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PasswordSecurity passwordSecurity;
|
private PasswordSecurity passwordSecurity;
|
||||||
|
|||||||
@ -3,8 +3,7 @@ package fr.xephi.authme.security;
|
|||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of hash algorithms supported by AuthMe. The linked {@link EncryptionMethod} implementation
|
* Hash algorithms supported by AuthMe.
|
||||||
* must be able to be instantiated with the default constructor.
|
|
||||||
*/
|
*/
|
||||||
public enum HashAlgorithm {
|
public enum HashAlgorithm {
|
||||||
|
|
||||||
@ -18,8 +17,8 @@ public enum HashAlgorithm {
|
|||||||
MD5(fr.xephi.authme.security.crypts.MD5.class),
|
MD5(fr.xephi.authme.security.crypts.MD5.class),
|
||||||
MD5VB(fr.xephi.authme.security.crypts.MD5VB.class),
|
MD5VB(fr.xephi.authme.security.crypts.MD5VB.class),
|
||||||
MYBB(fr.xephi.authme.security.crypts.MYBB.class),
|
MYBB(fr.xephi.authme.security.crypts.MYBB.class),
|
||||||
PBKDF2(fr.xephi.authme.security.crypts.CryptPBKDF2.class),
|
PBKDF2(fr.xephi.authme.security.crypts.Pbkdf2.class),
|
||||||
PBKDF2DJANGO(fr.xephi.authme.security.crypts.CryptPBKDF2Django.class),
|
PBKDF2DJANGO(fr.xephi.authme.security.crypts.Pbkdf2Django.class),
|
||||||
PHPBB(fr.xephi.authme.security.crypts.PHPBB.class),
|
PHPBB(fr.xephi.authme.security.crypts.PHPBB.class),
|
||||||
PHPFUSION(fr.xephi.authme.security.crypts.PHPFUSION.class),
|
PHPFUSION(fr.xephi.authme.security.crypts.PHPFUSION.class),
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
@ -6,12 +6,14 @@ import fr.xephi.authme.events.PasswordEncryptionEvent;
|
|||||||
import fr.xephi.authme.initialization.Reloadable;
|
import fr.xephi.authme.initialization.Reloadable;
|
||||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.settings.EnumSetProperty;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager class for password-related operations.
|
* Manager class for password-related operations.
|
||||||
@ -31,7 +33,7 @@ public class PasswordSecurity implements Reloadable {
|
|||||||
private Injector injector;
|
private Injector injector;
|
||||||
|
|
||||||
private HashAlgorithm algorithm;
|
private HashAlgorithm algorithm;
|
||||||
private boolean supportOldAlgorithm;
|
private Collection<HashAlgorithm> legacyAlgorithms;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load or reload the configuration.
|
* Load or reload the configuration.
|
||||||
@ -40,7 +42,8 @@ public class PasswordSecurity implements Reloadable {
|
|||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
|
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
|
||||||
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
|
// TODO #1014: Need to cast to specific type because ConfigMe ignores fields of child Property types
|
||||||
|
this.legacyAlgorithms = ((EnumSetProperty<HashAlgorithm>) SecuritySettings.LEGACY_HASHES).asEnumSet(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +86,7 @@ public class PasswordSecurity implements Reloadable {
|
|||||||
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
|
EncryptionMethod method = initializeEncryptionMethodWithEvent(algorithm, playerName);
|
||||||
String playerLowerCase = playerName.toLowerCase();
|
String playerLowerCase = playerName.toLowerCase();
|
||||||
return methodMatches(method, password, hashedPassword, playerLowerCase)
|
return methodMatches(method, password, hashedPassword, playerLowerCase)
|
||||||
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase);
|
|| compareWithLegacyHashes(password, hashedPassword, playerLowerCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,14 +100,12 @@ public class PasswordSecurity implements Reloadable {
|
|||||||
*
|
*
|
||||||
* @return True if there was a password match with another encryption method, false otherwise
|
* @return True if there was a password match with another encryption method, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean compareWithAllEncryptionMethods(String password, HashedPassword hashedPassword, String playerName) {
|
private boolean compareWithLegacyHashes(String password, HashedPassword hashedPassword, String playerName) {
|
||||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
for (HashAlgorithm algorithm : legacyAlgorithms) {
|
||||||
if (!HashAlgorithm.CUSTOM.equals(algorithm)) {
|
EncryptionMethod method = initializeEncryptionMethod(algorithm);
|
||||||
EncryptionMethod method = initializeEncryptionMethod(algorithm);
|
if (methodMatches(method, password, hashedPassword, playerName)) {
|
||||||
if (methodMatches(method, password, hashedPassword, playerName)) {
|
hashPasswordForNewAlgorithm(password, playerName);
|
||||||
hashPasswordForNewAlgorithm(password, playerName);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
package fr.xephi.authme.security.crypts;
|
|
||||||
|
|
||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
|
||||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
|
|
||||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
@Recommendation(Usage.DOES_NOT_WORK)
|
|
||||||
public class CryptPBKDF2 extends HexSaltedMethod {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String computeHash(String password, String salt, String name) {
|
|
||||||
String result = "pbkdf2_sha256$10000$" + salt + "$";
|
|
||||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000);
|
|
||||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
|
||||||
|
|
||||||
return result + Arrays.toString(engine.deriveKey(password, 64));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) {
|
|
||||||
String[] line = hashedPassword.getHash().split("\\$");
|
|
||||||
if (line.length != 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String salt = line[2];
|
|
||||||
String derivedKey = line[3];
|
|
||||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
|
|
||||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
|
||||||
return engine.verifyKey(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSaltLength() {
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -4,7 +4,7 @@ import fr.xephi.authme.security.HashUtils;
|
|||||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
import fr.xephi.authme.security.crypts.description.Usage;
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
|
||||||
@Recommendation(Usage.RECOMMENDED)
|
@Recommendation(Usage.ACCEPTABLE)
|
||||||
public class JOOMLA extends HexSaltedMethod {
|
public class JOOMLA extends HexSaltedMethod {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
package fr.xephi.authme.security.crypts;
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plaintext password storage.
|
||||||
|
*
|
||||||
|
* @deprecated Using this is no longer supported. AuthMe will migrate to SHA256 on startup.
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class PLAINTEXT extends UnsaltedMethod {
|
public class PLAINTEXT extends UnsaltedMethod {
|
||||||
|
|
||||||
|
|||||||
60
src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java
Normal file
60
src/main/java/fr/xephi/authme/security/crypts/Pbkdf2.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import de.rtner.misc.BinTools;
|
||||||
|
import de.rtner.security.auth.spi.PBKDF2Engine;
|
||||||
|
import de.rtner.security.auth.spi.PBKDF2Parameters;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||||
|
import fr.xephi.authme.security.crypts.description.Usage;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@Recommendation(Usage.RECOMMENDED)
|
||||||
|
public class Pbkdf2 extends HexSaltedMethod {
|
||||||
|
|
||||||
|
private static final int DEFAULT_ROUNDS = 10_000;
|
||||||
|
private int numberOfRounds;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Pbkdf2(Settings settings) {
|
||||||
|
int configuredRounds = settings.getProperty(SecuritySettings.PBKDF2_NUMBER_OF_ROUNDS);
|
||||||
|
this.numberOfRounds = configuredRounds > 0 ? configuredRounds : DEFAULT_ROUNDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String computeHash(String password, String salt, String name) {
|
||||||
|
String result = "pbkdf2_sha256$" + numberOfRounds + "$" + salt + "$";
|
||||||
|
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), numberOfRounds);
|
||||||
|
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||||
|
|
||||||
|
return result + BinTools.bin2hex(engine.deriveKey(password, 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean comparePassword(String password, HashedPassword hashedPassword, String unusedName) {
|
||||||
|
String[] line = hashedPassword.getHash().split("\\$");
|
||||||
|
if (line.length != 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int iterations;
|
||||||
|
try {
|
||||||
|
iterations = Integer.parseInt(line[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
ConsoleLogger.logException("Cannot read number of rounds for Pbkdf2", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String salt = line[2];
|
||||||
|
byte[] derivedKey = BinTools.hex2bin(line[3]);
|
||||||
|
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "UTF-8", salt.getBytes(), iterations, derivedKey);
|
||||||
|
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||||
|
return engine.verifyKey(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSaltLength() {
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,15 +1,14 @@
|
|||||||
package fr.xephi.authme.security.crypts;
|
package fr.xephi.authme.security.crypts;
|
||||||
|
|
||||||
|
import de.rtner.security.auth.spi.PBKDF2Engine;
|
||||||
|
import de.rtner.security.auth.spi.PBKDF2Parameters;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
|
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
|
||||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
|
|
||||||
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
|
|
||||||
import fr.xephi.authme.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
@AsciiRestricted
|
@AsciiRestricted
|
||||||
public class CryptPBKDF2Django extends HexSaltedMethod {
|
public class Pbkdf2Django extends HexSaltedMethod {
|
||||||
|
|
||||||
private static final int DEFAULT_ITERATIONS = 24000;
|
private static final int DEFAULT_ITERATIONS = 24000;
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
|
|||||||
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), DEFAULT_ITERATIONS);
|
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), DEFAULT_ITERATIONS);
|
||||||
PBKDF2Engine engine = new PBKDF2Engine(params);
|
PBKDF2Engine engine = new PBKDF2Engine(params);
|
||||||
|
|
||||||
return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
|
return result + DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -32,8 +31,7 @@ public class CryptPBKDF2Django extends HexSaltedMethod {
|
|||||||
try {
|
try {
|
||||||
iterations = Integer.parseInt(line[1]);
|
iterations = Integer.parseInt(line[1]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
ConsoleLogger.warning("Could not read number of rounds for CryptPBKDF2Django:"
|
ConsoleLogger.logException("Could not read number of rounds for Pbkdf2Django:", e);
|
||||||
+ StringUtils.formatException(e));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String salt = line[2];
|
String salt = line[2];
|
||||||
@ -18,14 +18,14 @@ public class XAUTH extends HexSaltedMethod {
|
|||||||
@Override
|
@Override
|
||||||
public String computeHash(String password, String salt, String name) {
|
public String computeHash(String password, String salt, String name) {
|
||||||
String hash = getWhirlpool(salt + password).toLowerCase();
|
String hash = getWhirlpool(salt + password).toLowerCase();
|
||||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||||
return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
|
return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
|
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
|
||||||
String hash = hashedPassword.getHash();
|
String hash = hashedPassword.getHash();
|
||||||
int saltPos = (password.length() >= hash.length() ? hash.length() - 1 : password.length());
|
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||||
if (saltPos + 12 > hash.length()) {
|
if (saltPos + 12 > hash.length()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,114 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free auxiliary functions. Copyright 2007, 2014, Matthias Gärtner
|
|
||||||
*
|
|
||||||
* This is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this software; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free auxiliary functions
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
*/
|
|
||||||
public class BinTools {
|
|
||||||
public static final String hex = "0123456789ABCDEF";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple binary-to-hexadecimal conversion.
|
|
||||||
*
|
|
||||||
* @param b
|
|
||||||
* Input bytes. May be <code>null</code>.
|
|
||||||
* @return Hexadecimal representation of b. Uppercase A-F, two characters
|
|
||||||
* per byte. Empty string on <code>null</code> input.
|
|
||||||
*/
|
|
||||||
public static String bin2hex(final byte[] b) {
|
|
||||||
if (b == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
StringBuffer sb = new StringBuffer(2 * b.length);
|
|
||||||
for (int i = 0; i < b.length; i++) {
|
|
||||||
int v = (256 + b[i]) % 256;
|
|
||||||
sb.append(hex.charAt((v / 16) & 15));
|
|
||||||
sb.append(hex.charAt((v % 16) & 15));
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert hex string to array of bytes.
|
|
||||||
*
|
|
||||||
* @param s
|
|
||||||
* String containing hexadecimal digits. May be <code>null</code>
|
|
||||||
* . On odd length leading zero will be assumed.
|
|
||||||
* @return Array on bytes, non-<code>null</code>.
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* when string contains non-hex character
|
|
||||||
*/
|
|
||||||
public static byte[] hex2bin(final String s) {
|
|
||||||
String m = s;
|
|
||||||
if (s == null) {
|
|
||||||
// Allow empty input string.
|
|
||||||
m = "";
|
|
||||||
} else if (s.length() % 2 != 0) {
|
|
||||||
// Assume leading zero for odd string length
|
|
||||||
m = "0" + s;
|
|
||||||
}
|
|
||||||
byte r[] = new byte[m.length() / 2];
|
|
||||||
for (int i = 0, n = 0; i < m.length(); n++) {
|
|
||||||
char h = m.charAt(i++);
|
|
||||||
char l = m.charAt(i++);
|
|
||||||
r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert hex digit to numerical value.
|
|
||||||
*
|
|
||||||
* @param c
|
|
||||||
* 0-9, a-f, A-F allowd.
|
|
||||||
* @return 0-15
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* on non-hex character
|
|
||||||
*/
|
|
||||||
public static int hex2bin(char c) {
|
|
||||||
if (c >= '0' && c <= '9') {
|
|
||||||
return (c - '0');
|
|
||||||
}
|
|
||||||
if (c >= 'A' && c <= 'F') {
|
|
||||||
return (c - 'A' + 10);
|
|
||||||
}
|
|
||||||
if (c >= 'a' && c <= 'f') {
|
|
||||||
return (c - 'a' + 10);
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
byte b[] = new byte[256];
|
|
||||||
byte bb = 0;
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
b[i] = bb++;
|
|
||||||
}
|
|
||||||
String s = bin2hex(b);
|
|
||||||
byte c[] = hex2bin(s);
|
|
||||||
String t = bin2hex(c);
|
|
||||||
if (!s.equals(t)) {
|
|
||||||
throw new AssertionError("Mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.NoSuchProviderException;
|
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Default PRF implementation based on standard javax.crypt.Mac mechanisms.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public class MacBasedPRF implements PRF {
|
|
||||||
|
|
||||||
protected Mac mac;
|
|
||||||
|
|
||||||
protected int hLen;
|
|
||||||
|
|
||||||
protected final String macAlgorithm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Mac-based Pseudo Random Function.
|
|
||||||
*
|
|
||||||
* @param macAlgorithm Mac algorithm to use, i.e. HMacSHA1 or HMacMD5.
|
|
||||||
*/
|
|
||||||
public MacBasedPRF(String macAlgorithm) {
|
|
||||||
this.macAlgorithm = macAlgorithm;
|
|
||||||
try {
|
|
||||||
mac = Mac.getInstance(macAlgorithm);
|
|
||||||
hLen = mac.getMacLength();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MacBasedPRF(String macAlgorithm, String provider) {
|
|
||||||
this.macAlgorithm = macAlgorithm;
|
|
||||||
try {
|
|
||||||
mac = Mac.getInstance(macAlgorithm, provider);
|
|
||||||
hLen = mac.getMacLength();
|
|
||||||
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] doFinal(byte[] M) {
|
|
||||||
byte[] r = mac.doFinal(M);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHLen() {
|
|
||||||
return hLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(byte[] P) {
|
|
||||||
try {
|
|
||||||
mac.init(new SecretKeySpec(P, macAlgorithm));
|
|
||||||
} catch (InvalidKeyException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public interface PBKDF2 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
|
||||||
* Desired key length defaults to Pseudo Random Function block size.
|
|
||||||
*
|
|
||||||
* @param inputPassword Candidate password to compute the derived key for.
|
|
||||||
*
|
|
||||||
* @return internal byte array
|
|
||||||
*/
|
|
||||||
byte[] deriveKey(String inputPassword);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert String-based input to internal byte array, then invoke PBKDF2.
|
|
||||||
*
|
|
||||||
* @param inputPassword Candidate password to compute the derived key for.
|
|
||||||
* @param dkLen Specify desired key length
|
|
||||||
*
|
|
||||||
* @return internal byte array
|
|
||||||
*/
|
|
||||||
byte[] deriveKey(String inputPassword, int dkLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert String-based input to internal byte arrays, then invoke PBKDF2
|
|
||||||
* and verify result against the reference data that is supplied in the
|
|
||||||
* PBKDF2Parameters.
|
|
||||||
*
|
|
||||||
* @param inputPassword Candidate password to compute the derived key for.
|
|
||||||
*
|
|
||||||
* @return <code>true</code> password match; <code>false</code> incorrect
|
|
||||||
* password
|
|
||||||
*/
|
|
||||||
boolean verifyKey(String inputPassword);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow reading of configured parameters.
|
|
||||||
*
|
|
||||||
* @return Currently set parameters.
|
|
||||||
*/
|
|
||||||
PBKDF2Parameters getParameters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow setting of configured parameters.
|
|
||||||
*
|
|
||||||
* @param parameters PBKDF2Parameters
|
|
||||||
*/
|
|
||||||
void setParameters(PBKDF2Parameters parameters);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get currently set Pseudo Random Function.
|
|
||||||
*
|
|
||||||
* @return Currently set Pseudo Random Function
|
|
||||||
*/
|
|
||||||
PRF getPseudoRandomFunction();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does
|
|
||||||
* init this object using the supplied candidate password. If this is
|
|
||||||
* undesired, one has to override getPRF.
|
|
||||||
*
|
|
||||||
* @param prf Pseudo Random Function to set.
|
|
||||||
*/
|
|
||||||
void setPseudoRandomFunction(PRF prf);
|
|
||||||
}
|
|
||||||
@ -1,346 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification
|
|
||||||
* </p><p>
|
|
||||||
* Version 2.0
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* PBKDF2 (P, S, c, dkLen)
|
|
||||||
* </p>
|
|
||||||
* Options:
|
|
||||||
* <ul>
|
|
||||||
* <li>PRF underlying pseudorandom function (hLen denotes the length in octets
|
|
||||||
* of the pseudorandom function output). PRF is pluggable.</li>
|
|
||||||
* </ul>
|
|
||||||
* Input:
|
|
||||||
* <ul>
|
|
||||||
* <li>P password, an octet string</li>
|
|
||||||
* <li>S salt, an octet string</li>
|
|
||||||
* <li>c iteration count, a positive integer</li>
|
|
||||||
* <li>dkLen intended length in octets of the derived key, a positive integer,
|
|
||||||
* at most (2^32 - 1) * hLen</li>
|
|
||||||
* </ul>
|
|
||||||
* Output:
|
|
||||||
* <ul>
|
|
||||||
* <li>DK derived key, a dkLen-octet string</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see
|
|
||||||
* <a href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" >http://www.
|
|
||||||
* gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>
|
|
||||||
*/
|
|
||||||
public class PBKDF2Engine implements PBKDF2 {
|
|
||||||
|
|
||||||
protected PBKDF2Parameters parameters;
|
|
||||||
|
|
||||||
protected PRF prf;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters must be
|
|
||||||
* passed later.
|
|
||||||
*/
|
|
||||||
public PBKDF2Engine() {
|
|
||||||
this.parameters = null;
|
|
||||||
prf = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
|
||||||
* passed so that this implementation knows iteration count, method to use
|
|
||||||
* and String encoding.
|
|
||||||
*
|
|
||||||
* @param parameters Data holder for iteration count, method to use et cetera.
|
|
||||||
*/
|
|
||||||
public PBKDF2Engine(PBKDF2Parameters parameters) {
|
|
||||||
this.parameters = parameters;
|
|
||||||
prf = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PBKDF2 implementation object. PBKDF2 parameters are
|
|
||||||
* passed so that this implementation knows iteration count, method to use
|
|
||||||
* and String encoding.
|
|
||||||
*
|
|
||||||
* @param parameters Data holder for iteration count, method to use et cetera.
|
|
||||||
* @param prf Supply customer Pseudo Random Function.
|
|
||||||
*/
|
|
||||||
public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf) {
|
|
||||||
this.parameters = parameters;
|
|
||||||
this.prf = prf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience client function. Convert supplied password with random 8-byte
|
|
||||||
* salt and 1000 iterations using HMacSHA1. Assume that password is in
|
|
||||||
* ISO-8559-1 encoding. Output result as
|
|
||||||
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
|
|
||||||
* encoding.
|
|
||||||
* <p>
|
|
||||||
* Example: Password "password" (without the quotes) leads to
|
|
||||||
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
|
|
||||||
* </p>
|
|
||||||
* @param args Supply the password as argument.
|
|
||||||
*
|
|
||||||
* @throws IOException an ioexception occured
|
|
||||||
* @throws NoSuchAlgorithmException a NoSuchAlgorithmException occured
|
|
||||||
*/
|
|
||||||
public static void main(String[] args)
|
|
||||||
throws IOException, NoSuchAlgorithmException {
|
|
||||||
String password = "password";
|
|
||||||
String candidate = null;
|
|
||||||
PBKDF2Formatter formatter = new PBKDF2HexFormatter();
|
|
||||||
|
|
||||||
if (args.length >= 1) {
|
|
||||||
password = args[0];
|
|
||||||
}
|
|
||||||
if (args.length >= 2) {
|
|
||||||
candidate = args[1];
|
|
||||||
}
|
|
||||||
if (candidate == null) {
|
|
||||||
// Creation mode
|
|
||||||
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
|
||||||
byte[] salt = new byte[8];
|
|
||||||
sr.nextBytes(salt);
|
|
||||||
int iterations = 1000;
|
|
||||||
PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", salt, iterations);
|
|
||||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
|
||||||
p.setDerivedKey(e.deriveKey(password));
|
|
||||||
candidate = formatter.toString(p);
|
|
||||||
} else {
|
|
||||||
// Verification mode
|
|
||||||
PBKDF2Parameters p = new PBKDF2Parameters();
|
|
||||||
p.setHashAlgorithm("HmacSHA1");
|
|
||||||
p.setHashCharset("ISO-8859-1");
|
|
||||||
if (formatter.fromString(p, candidate)) {
|
|
||||||
throw new IllegalArgumentException("Candidate data does not have correct format (\"" + candidate + "\")");
|
|
||||||
}
|
|
||||||
PBKDF2Engine e = new PBKDF2Engine(p);
|
|
||||||
boolean verifyOK = e.verifyKey(password);
|
|
||||||
System.exit(verifyOK ? 0 : 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] deriveKey(String inputPassword) {
|
|
||||||
return deriveKey(inputPassword, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] deriveKey(String inputPassword, int dkLen) {
|
|
||||||
byte[] r = null;
|
|
||||||
byte[] P = null;
|
|
||||||
String charset = parameters.getHashCharset();
|
|
||||||
if (inputPassword == null) {
|
|
||||||
inputPassword = "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (charset == null) {
|
|
||||||
P = inputPassword.getBytes();
|
|
||||||
} else {
|
|
||||||
P = inputPassword.getBytes(charset);
|
|
||||||
}
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
assertPRF(P);
|
|
||||||
if (dkLen == 0) {
|
|
||||||
dkLen = prf.getHLen();
|
|
||||||
}
|
|
||||||
r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), dkLen);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean verifyKey(String inputPassword) {
|
|
||||||
byte[] referenceKey = getParameters().getDerivedKey();
|
|
||||||
if (referenceKey == null || referenceKey.length == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
byte[] inputKey = deriveKey(inputPassword, referenceKey.length);
|
|
||||||
|
|
||||||
if (inputKey == null || inputKey.length != referenceKey.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < inputKey.length; i++) {
|
|
||||||
if (inputKey[i] != referenceKey[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method. Default implementation is (H)MAC-based. To be overridden
|
|
||||||
* in derived classes.
|
|
||||||
*
|
|
||||||
* @param P User-supplied candidate password as array of bytes.
|
|
||||||
*/
|
|
||||||
protected void assertPRF(byte[] P) {
|
|
||||||
if (prf == null) {
|
|
||||||
prf = new MacBasedPRF(parameters.getHashAlgorithm());
|
|
||||||
}
|
|
||||||
prf.init(P);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PRF getPseudoRandomFunction() {
|
|
||||||
return prf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPseudoRandomFunction(PRF prf) {
|
|
||||||
this.prf = prf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Core Password Based Key Derivation Function 2.
|
|
||||||
*
|
|
||||||
* @param prf Pseudo Random Function (i.e. HmacSHA1)
|
|
||||||
* @param S Salt as array of bytes. <code>null</code> means no salt.
|
|
||||||
* @param c Iteration count (see RFC 2898 4.2)
|
|
||||||
* @param dkLen desired length of derived key.
|
|
||||||
*
|
|
||||||
* @return internal byte array * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2</a>
|
|
||||||
*/
|
|
||||||
protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen) {
|
|
||||||
if (S == null) {
|
|
||||||
S = new byte[0];
|
|
||||||
}
|
|
||||||
int hLen = prf.getHLen();
|
|
||||||
int l = ceil(dkLen, hLen);
|
|
||||||
int r = dkLen - (l - 1) * hLen;
|
|
||||||
byte T[] = new byte[l * hLen];
|
|
||||||
int ti_offset = 0;
|
|
||||||
for (int i = 1; i <= l; i++) {
|
|
||||||
_F(T, ti_offset, prf, S, c, i);
|
|
||||||
ti_offset += hLen;
|
|
||||||
}
|
|
||||||
if (r < hLen) {
|
|
||||||
// Incomplete last block
|
|
||||||
byte DK[] = new byte[dkLen];
|
|
||||||
System.arraycopy(T, 0, DK, 0, dkLen);
|
|
||||||
return DK;
|
|
||||||
}
|
|
||||||
return T;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integer division with ceiling function.
|
|
||||||
*
|
|
||||||
* @param a Integer
|
|
||||||
* @param b Integer
|
|
||||||
*
|
|
||||||
* @return ceil(a/b) * @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
|
||||||
* 2.</a>
|
|
||||||
*/
|
|
||||||
protected int ceil(int a, int b) {
|
|
||||||
int m = 0;
|
|
||||||
if (a % b > 0) {
|
|
||||||
m = 1;
|
|
||||||
}
|
|
||||||
return a / b + m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function F.
|
|
||||||
*
|
|
||||||
* @param dest Destination byte buffer
|
|
||||||
* @param offset Offset into destination byte buffer
|
|
||||||
* @param prf Pseudo Random Function
|
|
||||||
* @param S Salt as array of bytes
|
|
||||||
* @param c Iteration count
|
|
||||||
* @param blockIndex Integer
|
|
||||||
*
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
|
||||||
* 3.</a>
|
|
||||||
*/
|
|
||||||
protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c,
|
|
||||||
int blockIndex) {
|
|
||||||
int hLen = prf.getHLen();
|
|
||||||
byte U_r[] = new byte[hLen];
|
|
||||||
|
|
||||||
// U0 = S || INT (i);
|
|
||||||
byte U_i[] = new byte[S.length + 4];
|
|
||||||
System.arraycopy(S, 0, U_i, 0, S.length);
|
|
||||||
INT(U_i, S.length, blockIndex);
|
|
||||||
|
|
||||||
for (int i = 0; i < c; i++) {
|
|
||||||
U_i = prf.doFinal(U_i);
|
|
||||||
xor(U_r, U_i);
|
|
||||||
}
|
|
||||||
System.arraycopy(U_r, 0, dest, offset, hLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Block-Xor. Xor source bytes into destination byte buffer. Destination
|
|
||||||
* buffer must be same length or less than source buffer.
|
|
||||||
*
|
|
||||||
* @param dest byte array
|
|
||||||
* @param src byte array
|
|
||||||
*/
|
|
||||||
protected void xor(byte[] dest, byte[] src) {
|
|
||||||
for (int i = 0; i < dest.length; i++) {
|
|
||||||
dest[i] ^= src[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Four-octet encoding of the integer i, most significant octet first.
|
|
||||||
*
|
|
||||||
* @param dest byte array
|
|
||||||
* @param offset Integer
|
|
||||||
* @param i Integer
|
|
||||||
*
|
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2898">RFC 2898 5.2 Step
|
|
||||||
* 3.</a>
|
|
||||||
*/
|
|
||||||
protected void INT(byte[] dest, int offset, int i) {
|
|
||||||
dest[offset] = (byte) (i / (256 * 256 * 256));
|
|
||||||
dest[offset + 1] = (byte) (i / (256 * 256));
|
|
||||||
dest[offset + 2] = (byte) (i / (256));
|
|
||||||
dest[offset + 3] = (byte) (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PBKDF2Parameters getParameters() {
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setParameters(PBKDF2Parameters parameters) {
|
|
||||||
this.parameters = parameters;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public interface PBKDF2Formatter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert parameters to String.
|
|
||||||
*
|
|
||||||
* @param p Parameters object to output.
|
|
||||||
*
|
|
||||||
* @return String representation
|
|
||||||
*/
|
|
||||||
String toString(PBKDF2Parameters p);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert String to parameters. Depending on actual implementation, it may
|
|
||||||
* be required to set further fields externally.
|
|
||||||
*
|
|
||||||
* @param s String representation of parameters to decode.
|
|
||||||
* @param p PBKDF2Parameters
|
|
||||||
*
|
|
||||||
* @return <code>false</code> syntax OK, <code>true</code> some syntax
|
|
||||||
* issue.
|
|
||||||
*/
|
|
||||||
boolean fromString(PBKDF2Parameters p, String s);
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public class PBKDF2HexFormatter implements PBKDF2Formatter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fromString(PBKDF2Parameters p, String s) {
|
|
||||||
if (p == null || s == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] p123 = s.split(":");
|
|
||||||
if (p123.length != 3) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte salt[] = BinTools.hex2bin(p123[0]);
|
|
||||||
int iterationCount = Integer.parseInt(p123[1]);
|
|
||||||
byte bDK[] = BinTools.hex2bin(p123[2]);
|
|
||||||
|
|
||||||
p.setSalt(salt);
|
|
||||||
p.setIterationCount(iterationCount);
|
|
||||||
p.setDerivedKey(bDK);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(PBKDF2Parameters p) {
|
|
||||||
String s = BinTools.bin2hex(p.getSalt()) + ":" + String.valueOf(p.getIterationCount()) + ":" + BinTools.bin2hex(p.getDerivedKey());
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,139 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Parameter data holder for PBKDF2 configuration.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public class PBKDF2Parameters {
|
|
||||||
|
|
||||||
protected byte[] salt;
|
|
||||||
|
|
||||||
protected int iterationCount;
|
|
||||||
|
|
||||||
protected String hashAlgorithm;
|
|
||||||
|
|
||||||
protected String hashCharset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The derived key is actually only a convenience to store a reference
|
|
||||||
* derived key. It is not used during computation.
|
|
||||||
*/
|
|
||||||
protected byte[] derivedKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. Defaults to <code>null</code> for byte arrays, UTF-8 as
|
|
||||||
* character set and 1000 for iteration count.
|
|
||||||
*/
|
|
||||||
public PBKDF2Parameters() {
|
|
||||||
this.hashAlgorithm = null;
|
|
||||||
this.hashCharset = "UTF-8";
|
|
||||||
this.salt = null;
|
|
||||||
this.iterationCount = 1000;
|
|
||||||
this.derivedKey = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param hashAlgorithm for example HMacSHA1 or HMacMD5
|
|
||||||
* @param hashCharset for example UTF-8
|
|
||||||
* @param salt Salt as byte array, may be <code>null</code> (not recommended)
|
|
||||||
* @param iterationCount Number of iterations to execute. Recommended value 1000.
|
|
||||||
*/
|
|
||||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
|
||||||
byte[] salt, int iterationCount) {
|
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
|
||||||
this.hashCharset = hashCharset;
|
|
||||||
this.salt = salt;
|
|
||||||
this.iterationCount = iterationCount;
|
|
||||||
this.derivedKey = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param hashAlgorithm for example HMacSHA1 or HMacMD5
|
|
||||||
* @param hashCharset for example UTF-8
|
|
||||||
* @param salt Salt as byte array, may be <code>null</code> (not recommended)
|
|
||||||
* @param iterationCount Number of iterations to execute. Recommended value 1000.
|
|
||||||
* @param derivedKey Convenience data holder, not used during computation.
|
|
||||||
*/
|
|
||||||
public PBKDF2Parameters(String hashAlgorithm, String hashCharset,
|
|
||||||
byte[] salt, int iterationCount, byte[] derivedKey) {
|
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
|
||||||
this.hashCharset = hashCharset;
|
|
||||||
this.salt = salt;
|
|
||||||
this.iterationCount = iterationCount;
|
|
||||||
this.derivedKey = derivedKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIterationCount() {
|
|
||||||
return iterationCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIterationCount(int iterationCount) {
|
|
||||||
this.iterationCount = iterationCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getSalt() {
|
|
||||||
return salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSalt(byte[] salt) {
|
|
||||||
this.salt = salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getDerivedKey() {
|
|
||||||
return derivedKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDerivedKey(byte[] derivedKey) {
|
|
||||||
this.derivedKey = derivedKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHashAlgorithm() {
|
|
||||||
return hashAlgorithm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHashAlgorithm(String hashAlgorithm) {
|
|
||||||
this.hashAlgorithm = hashAlgorithm;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHashCharset() {
|
|
||||||
return hashCharset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHashCharset(String hashCharset) {
|
|
||||||
this.hashCharset = hashCharset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package fr.xephi.authme.security.pbkdf2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* A free Java implementation of Password Based Key Derivation Function 2 as
|
|
||||||
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is free software; you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Lesser General Public License as published by the Free
|
|
||||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
* details.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this library; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* For Details, see <a
|
|
||||||
* href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
|
|
||||||
* >http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html</a>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Matthias Gärtner
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
public interface PRF {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize this instance with the user-supplied password.
|
|
||||||
*
|
|
||||||
* @param P The password supplied as array of bytes. It is the caller's
|
|
||||||
* task to convert String passwords to bytes as appropriate.
|
|
||||||
*/
|
|
||||||
void init(byte[] P);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pseudo Random Function
|
|
||||||
*
|
|
||||||
* @param M Input data/message etc. Together with any data supplied during
|
|
||||||
* initilization.
|
|
||||||
*
|
|
||||||
* @return Random bytes of hLen length.
|
|
||||||
*/
|
|
||||||
byte[] doFinal(byte[] M);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query block size of underlying algorithm/mechanism.
|
|
||||||
*
|
|
||||||
* @return block size
|
|
||||||
*/
|
|
||||||
int getHLen();
|
|
||||||
}
|
|
||||||
@ -7,10 +7,11 @@ import fr.xephi.authme.permission.AdminPermission;
|
|||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||||
@ -25,18 +26,18 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
private final Messages messages;
|
private final Messages messages;
|
||||||
private final PermissionsManager permissionsManager;
|
private final PermissionsManager permissionsManager;
|
||||||
private final BukkitService bukkitService;
|
private final BukkitService bukkitService;
|
||||||
|
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList<>();
|
||||||
// Settings
|
// Settings
|
||||||
private int duration;
|
private int duration;
|
||||||
private int sensibility;
|
private int sensibility;
|
||||||
private int delay;
|
private int delay;
|
||||||
|
private int interval;
|
||||||
// Service status
|
// Service status
|
||||||
private AntiBotStatus antiBotStatus;
|
private AntiBotStatus antiBotStatus;
|
||||||
private boolean startup;
|
private boolean startup;
|
||||||
private BukkitTask disableTask;
|
private BukkitTask disableTask;
|
||||||
private int antibotPlayers;
|
private Instant lastFlaggedJoin;
|
||||||
private final CopyOnWriteArrayList<String> antibotKicked = new CopyOnWriteArrayList<>();
|
private int flagged = 0;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AntiBotService(Settings settings, Messages messages, PermissionsManager permissionsManager,
|
AntiBotService(Settings settings, Messages messages, PermissionsManager permissionsManager,
|
||||||
@ -47,7 +48,7 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
this.bukkitService = bukkitService;
|
this.bukkitService = bukkitService;
|
||||||
// Initial status
|
// Initial status
|
||||||
disableTask = null;
|
disableTask = null;
|
||||||
antibotPlayers = 0;
|
flagged = 0;
|
||||||
antiBotStatus = AntiBotStatus.DISABLED;
|
antiBotStatus = AntiBotStatus.DISABLED;
|
||||||
startup = true;
|
startup = true;
|
||||||
// Load settings and start if required
|
// Load settings and start if required
|
||||||
@ -60,6 +61,7 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
|
duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
|
||||||
sensibility = settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY);
|
sensibility = settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY);
|
||||||
delay = settings.getProperty(ProtectionSettings.ANTIBOT_DELAY);
|
delay = settings.getProperty(ProtectionSettings.ANTIBOT_DELAY);
|
||||||
|
interval = settings.getProperty(ProtectionSettings.ANTIBOT_INTERVAL);
|
||||||
|
|
||||||
// Stop existing protection
|
// Stop existing protection
|
||||||
stopProtection();
|
stopProtection();
|
||||||
@ -71,15 +73,10 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bot activation task
|
// Bot activation task
|
||||||
Runnable enableTask = new Runnable() {
|
Runnable enableTask = () -> antiBotStatus = AntiBotStatus.LISTENING;
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
antiBotStatus = AntiBotStatus.LISTENING;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Delay the schedule on first start
|
// Delay the schedule on first start
|
||||||
if(startup) {
|
if (startup) {
|
||||||
bukkitService.scheduleSyncDelayedTask(enableTask, delay * TICKS_PER_SECOND);
|
bukkitService.scheduleSyncDelayedTask(enableTask, delay * TICKS_PER_SECOND);
|
||||||
startup = false;
|
startup = false;
|
||||||
} else {
|
} else {
|
||||||
@ -94,19 +91,12 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
antiBotStatus = AntiBotStatus.ACTIVE;
|
antiBotStatus = AntiBotStatus.ACTIVE;
|
||||||
|
|
||||||
// Inform admins
|
// Inform admins
|
||||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
bukkitService.getOnlinePlayers().stream()
|
||||||
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
|
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES))
|
||||||
messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE);
|
.forEach(player -> messages.send(player, MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule auto-disable
|
// Schedule auto-disable
|
||||||
disableTask = bukkitService.runTaskLater(new Runnable() {
|
disableTask = bukkitService.runTaskLater(this::stopProtection, duration * TICKS_PER_MINUTE);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
stopProtection();
|
|
||||||
}
|
|
||||||
}, duration * TICKS_PER_MINUTE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopProtection() {
|
private void stopProtection() {
|
||||||
@ -116,7 +106,7 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
|
|
||||||
// Change status
|
// Change status
|
||||||
antiBotStatus = AntiBotStatus.LISTENING;
|
antiBotStatus = AntiBotStatus.LISTENING;
|
||||||
antibotPlayers = 0;
|
flagged = 0;
|
||||||
antibotKicked.clear();
|
antibotKicked.clear();
|
||||||
|
|
||||||
// Cancel auto-disable task
|
// Cancel auto-disable task
|
||||||
@ -124,11 +114,10 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
disableTask = null;
|
disableTask = null;
|
||||||
|
|
||||||
// Inform admins
|
// Inform admins
|
||||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
String durationString = Integer.toString(duration);
|
||||||
if (permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES)) {
|
bukkitService.getOnlinePlayers().stream()
|
||||||
messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, Integer.toString(duration));
|
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.ANTIBOT_MESSAGES))
|
||||||
}
|
.forEach(player -> messages.send(player, MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, durationString));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,36 +144,33 @@ public class AntiBotService implements SettingsDependent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a player joining the server and checks if AntiBot needs to be activated.
|
|
||||||
*/
|
|
||||||
public void handlePlayerJoin() {
|
|
||||||
if (antiBotStatus != AntiBotStatus.LISTENING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
antibotPlayers++;
|
|
||||||
if (antibotPlayers > sensibility) {
|
|
||||||
startProtection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bukkitService.scheduleSyncDelayedTask(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
antibotPlayers--;
|
|
||||||
}
|
|
||||||
}, 5 * TICKS_PER_SECOND);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if a player should be kicked due to antibot service.
|
* Returns if a player should be kicked due to antibot service.
|
||||||
*
|
*
|
||||||
* @param isAuthAvailable if the player is registered
|
|
||||||
* @return if the player should be kicked
|
* @return if the player should be kicked
|
||||||
*/
|
*/
|
||||||
public boolean shouldKick(boolean isAuthAvailable) {
|
public boolean shouldKick() {
|
||||||
return !isAuthAvailable && (antiBotStatus == AntiBotStatus.ACTIVE);
|
if (antiBotStatus == AntiBotStatus.DISABLED) {
|
||||||
|
return false;
|
||||||
|
} else if (antiBotStatus == AntiBotStatus.ACTIVE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastFlaggedJoin == null) {
|
||||||
|
lastFlaggedJoin = Instant.now();
|
||||||
|
}
|
||||||
|
if (ChronoUnit.SECONDS.between(lastFlaggedJoin, Instant.now()) <= interval) {
|
||||||
|
flagged++;
|
||||||
|
} else {
|
||||||
|
// reset to 1 because this player is also count as not registered
|
||||||
|
flagged = 1;
|
||||||
|
lastFlaggedJoin = null;
|
||||||
|
}
|
||||||
|
if (flagged > sensibility) {
|
||||||
|
startProtection();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -104,36 +104,22 @@ public class BackupService {
|
|||||||
dirBackup.mkdir();
|
dirBackup.mkdir();
|
||||||
}
|
}
|
||||||
String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH);
|
String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH);
|
||||||
if (checkWindows(backupWindowsPath)) {
|
boolean isUsingWindows = checkWindows(backupWindowsPath);
|
||||||
String executeCmd = backupWindowsPath + "\\bin\\mysqldump.exe -u " + dbUserName + " -p" + dbPassword + " " + dbName + " --tables " + tblname + " -r " + path + ".sql";
|
String backupCommand = isUsingWindows
|
||||||
Process runtimeProcess;
|
? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments()
|
||||||
try {
|
: "mysqldump" + buildMysqlDumpArguments();
|
||||||
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
|
|
||||||
int processComplete = runtimeProcess.waitFor();
|
try {
|
||||||
if (processComplete == 0) {
|
Process runtimeProcess = Runtime.getRuntime().exec(backupCommand);
|
||||||
ConsoleLogger.info("Backup created successfully.");
|
int processComplete = runtimeProcess.waitFor();
|
||||||
return true;
|
if (processComplete == 0) {
|
||||||
} else {
|
ConsoleLogger.info("Backup created successfully. (Using Windows = " + isUsingWindows + ")");
|
||||||
ConsoleLogger.warning("Could not create the backup! (Windows)");
|
return true;
|
||||||
}
|
} else {
|
||||||
} catch (IOException | InterruptedException e) {
|
ConsoleLogger.warning("Could not create the backup! (Using Windows = " + isUsingWindows + ")");
|
||||||
ConsoleLogger.logException("Error during Windows backup:", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String executeCmd = "mysqldump -u " + dbUserName + " -p" + dbPassword + " " + dbName + " --tables " + tblname + " -r " + path + ".sql";
|
|
||||||
Process runtimeProcess;
|
|
||||||
try {
|
|
||||||
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
|
|
||||||
int processComplete = runtimeProcess.waitFor();
|
|
||||||
if (processComplete == 0) {
|
|
||||||
ConsoleLogger.info("Backup created successfully.");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
ConsoleLogger.warning("Could not create the backup!");
|
|
||||||
}
|
|
||||||
} catch (IOException | InterruptedException e) {
|
|
||||||
ConsoleLogger.logException("Error during backup:", e);
|
|
||||||
}
|
}
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
ConsoleLogger.logException("Error during backup (using Windows = " + isUsingWindows + "):", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -173,6 +159,16 @@ public class BackupService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the command line arguments to pass along when running the {@code mysqldump} command.
|
||||||
|
*
|
||||||
|
* @return the mysqldump command line arguments
|
||||||
|
*/
|
||||||
|
private String buildMysqlDumpArguments() {
|
||||||
|
return " -u " + dbUserName + " -p" + dbPassword + " " + dbName
|
||||||
|
+ " --tables " + tblname + " -r " + path + ".sql";
|
||||||
|
}
|
||||||
|
|
||||||
private static void copy(String src, String dst) throws IOException {
|
private static void copy(String src, String dst) throws IOException {
|
||||||
InputStream in = new FileInputStream(src);
|
InputStream in = new FileInputStream(src);
|
||||||
OutputStream out = new FileOutputStream(dst);
|
OutputStream out = new FileOutputStream(dst);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import org.bukkit.BanList;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
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.plugin.Plugin;
|
||||||
@ -17,6 +18,7 @@ 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;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -40,7 +42,8 @@ public class BukkitService implements SettingsDependent {
|
|||||||
private Method getOnlinePlayers;
|
private Method getOnlinePlayers;
|
||||||
private boolean useAsyncTasks;
|
private boolean useAsyncTasks;
|
||||||
|
|
||||||
public BukkitService(AuthMe authMe, Settings settings) {
|
@Inject
|
||||||
|
BukkitService(AuthMe authMe, Settings settings) {
|
||||||
this.authMe = authMe;
|
this.authMe = authMe;
|
||||||
getOnlinePlayersIsCollection = initializeOnlinePlayersIsCollectionField();
|
getOnlinePlayersIsCollection = initializeOnlinePlayersIsCollectionField();
|
||||||
reload(settings);
|
reload(settings);
|
||||||
@ -271,6 +274,27 @@ public class BukkitService implements SettingsDependent {
|
|||||||
return Bukkit.getWorld(name);
|
return Bukkit.getWorld(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a command on this server, and executes it if found.
|
||||||
|
*
|
||||||
|
* @param sender the apparent sender of the command
|
||||||
|
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
|
||||||
|
* @return returns false if no target is found
|
||||||
|
*/
|
||||||
|
public boolean dispatchCommand(CommandSender sender, String commandLine) {
|
||||||
|
return Bukkit.dispatchCommand(sender, commandLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a command to be run as console user on this server, and executes it if found.
|
||||||
|
*
|
||||||
|
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
|
||||||
|
* @return returns false if no target is found
|
||||||
|
*/
|
||||||
|
public boolean dispatchConsoleCommand(String commandLine) {
|
||||||
|
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), commandLine);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(Settings settings) {
|
public void reload(Settings settings) {
|
||||||
useAsyncTasks = settings.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
useAsyncTasks = settings.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
||||||
@ -307,5 +331,4 @@ public class BukkitService implements SettingsDependent {
|
|||||||
public BanEntry banIp(String ip, String reason, Date expires, String source) {
|
public BanEntry banIp(String ip, String reason, Date expires, String source) {
|
||||||
return Bukkit.getServer().getBanList(BanList.Type.IP).addBan(ip, reason, expires, source);
|
return Bukkit.getServer().getBanList(BanList.Type.IP).addBan(ip, reason, expires, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package fr.xephi.authme.process;
|
package fr.xephi.authme.service;
|
||||||
|
|
||||||
import com.github.authme.configme.properties.Property;
|
import com.github.authme.configme.properties.Property;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
@ -8,16 +8,15 @@ import fr.xephi.authme.permission.AuthGroupType;
|
|||||||
import fr.xephi.authme.permission.PermissionNode;
|
import fr.xephi.authme.permission.PermissionNode;
|
||||||
import fr.xephi.authme.permission.PermissionsManager;
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for asynchronous and synchronous processes.
|
* Service for the most common operations regarding settings, messages and permissions.
|
||||||
*/
|
*/
|
||||||
public class ProcessService {
|
public class CommonService {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
@ -25,17 +24,17 @@ public class ProcessService {
|
|||||||
@Inject
|
@Inject
|
||||||
private Messages messages;
|
private Messages messages;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private ValidationService validationService;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PermissionsManager permissionsManager;
|
private PermissionsManager permissionsManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private AuthGroupHandler authGroupHandler;
|
private AuthGroupHandler authGroupHandler;
|
||||||
|
|
||||||
|
CommonService() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a property's value.
|
* Retrieves a property's value.
|
||||||
*
|
*
|
||||||
* @param property the property to retrieve
|
* @param property the property to retrieve
|
||||||
* @param <T> the property type
|
* @param <T> the property type
|
||||||
@ -46,16 +45,7 @@ public class ProcessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the settings manager.
|
* Sends a message to the command sender.
|
||||||
*
|
|
||||||
* @return settings manager
|
|
||||||
*/
|
|
||||||
public Settings getSettings() {
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a message to the command sender.
|
|
||||||
*
|
*
|
||||||
* @param sender the command sender
|
* @param sender the command sender
|
||||||
* @param key the message key
|
* @param key the message key
|
||||||
@ -65,7 +55,7 @@ public class ProcessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the command sender with the given replacements.
|
* Sends a message to the command sender with the given replacements.
|
||||||
*
|
*
|
||||||
* @param sender the command sender
|
* @param sender the command sender
|
||||||
* @param key the message key
|
* @param key the message key
|
||||||
@ -76,7 +66,7 @@ public class ProcessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a message.
|
* Retrieves a message.
|
||||||
*
|
*
|
||||||
* @param key the key of the message
|
* @param key the key of the message
|
||||||
* @return the message, split by line
|
* @return the message, split by line
|
||||||
@ -86,7 +76,7 @@ public class ProcessService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a message as one piece.
|
* Retrieves a message in one piece.
|
||||||
*
|
*
|
||||||
* @param key the key of the message
|
* @param key the key of the message
|
||||||
* @return the message
|
* @return the message
|
||||||
@ -95,18 +85,24 @@ public class ProcessService {
|
|||||||
return messages.retrieveSingle(key);
|
return messages.retrieveSingle(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateEmail(String email) {
|
/**
|
||||||
return validationService.validateEmail(email);
|
* Checks whether the player has the given permission.
|
||||||
}
|
*
|
||||||
|
* @param player the player
|
||||||
public boolean isEmailFreeForRegistration(String email, CommandSender sender) {
|
* @param node the permission node to check
|
||||||
return validationService.isEmailFreeForRegistration(email, sender);
|
* @return true if player has permission, false otherwise
|
||||||
}
|
*/
|
||||||
|
|
||||||
public boolean hasPermission(Player player, PermissionNode node) {
|
public boolean hasPermission(Player player, PermissionNode node) {
|
||||||
return permissionsManager.hasPermission(player, node);
|
return permissionsManager.hasPermission(player, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the permission group of the given player.
|
||||||
|
*
|
||||||
|
* @param player the player to process
|
||||||
|
* @param group the group to add the player to
|
||||||
|
* @return true on success, false otherwise
|
||||||
|
*/
|
||||||
public boolean setGroup(Player player, AuthGroupType group) {
|
public boolean setGroup(Player player, AuthGroupType group) {
|
||||||
return authGroupHandler.setGroup(player, group);
|
return authGroupHandler.setGroup(player, group);
|
||||||
}
|
}
|
||||||
@ -17,6 +17,8 @@ import java.net.URLConnection;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import static com.maxmind.geoip.LookupService.GEOIP_MEMORY_CACHE;
|
||||||
|
|
||||||
public class GeoIpService {
|
public class GeoIpService {
|
||||||
private static final String LICENSE =
|
private static final String LICENSE =
|
||||||
"[LICENSE] This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com";
|
"[LICENSE] This product uses data from the GeoLite API created by MaxMind, available at http://www.maxmind.com";
|
||||||
@ -57,7 +59,7 @@ public class GeoIpService {
|
|||||||
boolean dataIsOld = (System.currentTimeMillis() - dataFile.lastModified()) > TimeUnit.DAYS.toMillis(30);
|
boolean dataIsOld = (System.currentTimeMillis() - dataFile.lastModified()) > TimeUnit.DAYS.toMillis(30);
|
||||||
if (!dataIsOld) {
|
if (!dataIsOld) {
|
||||||
try {
|
try {
|
||||||
lookupService = new LookupService(dataFile);
|
lookupService = new LookupService(dataFile, GEOIP_MEMORY_CACHE);
|
||||||
ConsoleLogger.info(LICENSE);
|
ConsoleLogger.info(LICENSE);
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@ -57,7 +57,7 @@ public class MessageUpdater {
|
|||||||
|
|
||||||
properties = buildPropertyEntriesForMessageKeys();
|
properties = buildPropertyEntriesForMessageKeys();
|
||||||
settingsManager = new SettingsManager(
|
settingsManager = new SettingsManager(
|
||||||
new YamlFileResource(userFile), (r, p) -> true, new ConfigurationData((List) properties));
|
new YamlFileResource(userFile), null, new ConfigurationData(properties));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,7 +85,6 @@ public class MessageUpdater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void copyMissingMessages() {
|
private void copyMissingMessages() {
|
||||||
for (Property<String> property : properties) {
|
for (Property<String> property : properties) {
|
||||||
String message = userConfiguration.getString(property.getPath());
|
String message = userConfiguration.getString(property.getPath());
|
||||||
|
|||||||
@ -40,7 +40,8 @@ public class ValidationService implements Reloadable {
|
|||||||
private Pattern passwordRegex;
|
private Pattern passwordRegex;
|
||||||
private Set<String> unrestrictedNames;
|
private Set<String> unrestrictedNames;
|
||||||
|
|
||||||
ValidationService() { }
|
ValidationService() {
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
46
src/main/java/fr/xephi/authme/settings/EnumSetProperty.java
Normal file
46
src/main/java/fr/xephi/authme/settings/EnumSetProperty.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
|
import com.github.authme.configme.SettingsManager;
|
||||||
|
import com.github.authme.configme.properties.StringListProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property whose value is a set of entries of a given enum.
|
||||||
|
*/
|
||||||
|
// TODO #1014: This property type currently extends StringListProperty with a dedicated method to convert the values
|
||||||
|
// into a Set of the selected enum due to multiple issues on ConfigMe's side.
|
||||||
|
public class EnumSetProperty<E extends Enum<E>> extends StringListProperty {
|
||||||
|
|
||||||
|
private final Class<E> enumClass;
|
||||||
|
|
||||||
|
public EnumSetProperty(Class<E> enumClass, String path, String... values) {
|
||||||
|
super(path, values);
|
||||||
|
this.enumClass = enumClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value as a set of enum entries.
|
||||||
|
*
|
||||||
|
* @param settings the settings manager to look up the raw value with
|
||||||
|
* @return the property's value as mapped enum entries
|
||||||
|
*/
|
||||||
|
public Set<E> asEnumSet(SettingsManager settings) {
|
||||||
|
List<String> entries = settings.getProperty(this);
|
||||||
|
return entries.stream()
|
||||||
|
.map(str -> toEnum(str))
|
||||||
|
.filter(e -> e != null)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private E toEnum(String str) {
|
||||||
|
for (E e : enumClass.getEnumConstants()) {
|
||||||
|
if (str.equalsIgnoreCase(e.name())) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user