mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-22 16:48:21 +01:00
Email verification code (#1382)
* Base verification code implementation, must define command, manager, events * VerificationManager, verification command and messages, handled some sensible commands, configuration values * Improved manager and sensible commands trigger * Updated messages * Updated verification code manager, fixed tests * Switched to a permission based command * Verification manager and command improved and added tests * Edited messages
This commit is contained in:
parent
8422581a82
commit
ba65633182
@ -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 08 19:56:41 CEST 2017. See docs/commands/commands.tpl.md -->
|
<!-- File auto-generated on Sat Oct 28 10:39:36 CEST 2017. 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 `< >`
|
||||||
@ -32,7 +32,7 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||||||
<br />Requires `authme.admin.firstspawn`
|
<br />Requires `authme.admin.firstspawn`
|
||||||
- **/authme setfirstspawn**: Change the first player's spawn to your current position.
|
- **/authme setfirstspawn**: Change the first player's spawn to your current position.
|
||||||
<br />Requires `authme.admin.setfirstspawn`
|
<br />Requires `authme.admin.setfirstspawn`
|
||||||
- **/authme purge** <days> [all]: Purge old AuthMeReloaded data longer than the specified number of days ago.
|
- **/authme purge** <days>: Purge old AuthMeReloaded data longer than the specified number of days ago.
|
||||||
<br />Requires `authme.admin.purge`
|
<br />Requires `authme.admin.purge`
|
||||||
- **/authme purgeplayer** <player> [options]: Purges data of the given player.
|
- **/authme purgeplayer** <player> [options]: Purges data of the given player.
|
||||||
<br />Requires `authme.admin.purgeplayer`
|
<br />Requires `authme.admin.purgeplayer`
|
||||||
@ -86,8 +86,11 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||||||
- **/captcha** <captcha>: Captcha command for AuthMeReloaded.
|
- **/captcha** <captcha>: Captcha command for AuthMeReloaded.
|
||||||
<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.
|
||||||
|
- **/verification** <code>: Command to complete the verification process for AuthMeReloaded.
|
||||||
|
<br />Requires `authme.player.security.verificationcode`
|
||||||
|
- **/verification help** [query]: View detailed help for /verification commands.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Oct 08 19:56:41 CEST 2017
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 28 10:39:36 CEST 2017
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Tue Oct 10 13:51:56 CEST 2017. See docs/config/config.tpl.md -->
|
<!-- File auto-generated on Sat Oct 28 10:39:36 CEST 2017. See docs/config/config.tpl.md -->
|
||||||
|
|
||||||
## AuthMe Configuration
|
## AuthMe Configuration
|
||||||
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||||
@ -43,10 +43,14 @@ DataSource:
|
|||||||
mySQLColumnLogged: 'isLogged'
|
mySQLColumnLogged: 'isLogged'
|
||||||
# Column for storing if a player has a valid session or not
|
# Column for storing if a player has a valid session or not
|
||||||
mySQLColumnHasSession: 'hasSession'
|
mySQLColumnHasSession: 'hasSession'
|
||||||
# Column for storing players ips
|
# Column for storing the player's last IP
|
||||||
mySQLColumnIp: 'ip'
|
mySQLColumnIp: 'ip'
|
||||||
# Column for storing players lastlogins
|
# Column for storing players lastlogins
|
||||||
mySQLColumnLastLogin: 'lastlogin'
|
mySQLColumnLastLogin: 'lastlogin'
|
||||||
|
# Column storing the registration date
|
||||||
|
mySQLColumnRegisterDate: 'regdate'
|
||||||
|
# Column for storing the IP address at the time of registration
|
||||||
|
mySQLColumnRegisterIp: 'regip'
|
||||||
# Column for storing player LastLocation - X
|
# Column for storing player LastLocation - X
|
||||||
mySQLlastlocX: 'x'
|
mySQLlastlocX: 'x'
|
||||||
# Column for storing player LastLocation - Y
|
# Column for storing player LastLocation - Y
|
||||||
@ -226,10 +230,11 @@ settings:
|
|||||||
minPasswordLength: 5
|
minPasswordLength: 5
|
||||||
# Maximum length of password
|
# Maximum length of password
|
||||||
passwordMaxLength: 30
|
passwordMaxLength: 30
|
||||||
# Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512, WHIRLPOOL,
|
# Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,
|
||||||
# MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,
|
# MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,
|
||||||
# PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (for developers only). See full list at
|
# PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, CUSTOM (for developers only). See full list at
|
||||||
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md
|
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md
|
||||||
|
# If you use ARGON2, check that you have the argon2 c library on your system
|
||||||
passwordHash: 'SHA256'
|
passwordHash: 'SHA256'
|
||||||
# If a password check fails, AuthMe will also try to check with the following hash methods.
|
# 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.
|
# Use this setting when you change from one hash method to another.
|
||||||
@ -470,6 +475,8 @@ Security:
|
|||||||
# original email: my.email@example.com
|
# original email: my.email@example.com
|
||||||
# hidden email: my.***@***mple.com
|
# hidden email: my.***@***mple.com
|
||||||
enableEmailMasking: false
|
enableEmailMasking: false
|
||||||
|
# Minutes after which a verification code will expire
|
||||||
|
verificationCodeExpiration: 10
|
||||||
# Before a user logs in, various properties are temporarily removed from the player,
|
# Before a user logs in, various properties are temporarily removed from the player,
|
||||||
# such as OP status, ability to fly, and walk/fly speed.
|
# such as OP status, ability to fly, and walk/fly speed.
|
||||||
# Once the user is logged in, we add back the properties we previously saved.
|
# Once the user is logged in, we add back the properties we previously saved.
|
||||||
@ -547,4 +554,4 @@ To change settings on a running server, save your changes to config.yml and use
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Tue Oct 10 13:51:56 CEST 2017
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 28 10:39:36 CEST 2017
|
||||||
|
@ -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 Sep 02 12:24:17 CEST 2017. See docs/permissions/permission_nodes.tpl.md -->
|
<!-- File auto-generated on Sat Oct 28 12:12:40 CEST 2017. See docs/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.
|
||||||
@ -40,6 +40,7 @@ The following are the permission nodes that are currently supported by the lates
|
|||||||
- **authme.debug.group** – Permission to view permission groups.
|
- **authme.debug.group** – Permission to view permission groups.
|
||||||
- **authme.debug.limbo** – Permission to use the limbo data viewer.
|
- **authme.debug.limbo** – Permission to use the limbo data viewer.
|
||||||
- **authme.debug.mail** – Permission to use the test email sender.
|
- **authme.debug.mail** – Permission to use the test email sender.
|
||||||
|
- **authme.debug.mysqldef** – Permission to change nullable status of MySQL columns.
|
||||||
- **authme.debug.perm** – Permission to use the permission checker.
|
- **authme.debug.perm** – Permission to use the permission checker.
|
||||||
- **authme.debug.spawn** – Permission to view spawn information.
|
- **authme.debug.spawn** – Permission to view spawn information.
|
||||||
- **authme.debug.stats** – Permission to use the stats section.
|
- **authme.debug.stats** – Permission to use the stats section.
|
||||||
@ -56,6 +57,7 @@ The following are the permission nodes that are currently supported by the lates
|
|||||||
- **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.security.verificationcode** – Permission to use the email verification codes feature.
|
||||||
- **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** – When the server is full and someone with this permission joins the server, someone will be kicked.
|
- **authme.vip** – When the server is full and someone with this permission joins the server, someone will be kicked.
|
||||||
@ -63,4 +65,4 @@ The following are the permission nodes that are currently supported by the lates
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Sep 02 12:24:17 CEST 2017
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 28 12:12:40 CEST 2017
|
||||||
|
@ -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 Sep 17 11:29:08 CEST 2017. See docs/translations/translations.tpl.md -->
|
<!-- File auto-generated on Sat Oct 28 11:30:40 CEST 2017. 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,37 +8,37 @@ 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 | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 88% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=88&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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 53% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=53&h=5&txtpad=1" alt="bar" />
|
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 49% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=49&h=5&txtpad=1" alt="bar" />
|
||||||
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 56% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=56&h=5&txtpad=1" alt="bar" />
|
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 52% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=52&h=5&txtpad=1" alt="bar" />
|
||||||
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 60% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=60&h=5&txtpad=1" alt="bar" />
|
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 55% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=55&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 | 91% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=91&h=5&txtpad=1" alt="bar" />
|
||||||
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 59% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=59&h=5&txtpad=1" alt="bar" />
|
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 54% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb6600&w=54&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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 85% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=99bb22&w=85&h=5&txtpad=1" alt="bar" />
|
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 78% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=78&h=5&txtpad=1" alt="bar" />
|
||||||
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 45% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa5500&w=45&h=5&txtpad=1" alt="bar" />
|
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 41% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aa4400&w=41&h=5&txtpad=1" alt="bar" />
|
||||||
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&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" />
|
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&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" />
|
[ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&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" />
|
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 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 | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 95% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=95&h=5&txtpad=1" alt="bar" />
|
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 88% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=88&h=5&txtpad=1" alt="bar" />
|
||||||
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 79% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb9900&w=79&h=5&txtpad=1" alt="bar" />
|
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 73% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=73&h=5&txtpad=1" alt="bar" />
|
||||||
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 96% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ee55&w=96&h=5&txtpad=1" alt="bar" />
|
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 89% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=88cc33&w=89&h=5&txtpad=1" alt="bar" />
|
||||||
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 100% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=66ff66&w=100&h=5&txtpad=1" alt="bar" />
|
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 68% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=68&h=5&txtpad=1" alt="bar" />
|
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 92% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=77dd44&w=92&h=5&txtpad=1" alt="bar" />
|
||||||
[zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 81% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=aaaa11&w=81&h=5&txtpad=1" alt="bar" />
|
[zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 75% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=cc9900&w=75&h=5&txtpad=1" alt="bar" />
|
||||||
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 68% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb8800&w=68&h=5&txtpad=1" alt="bar" />
|
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 63% | <img src="https://placeholdit.imgix.net/~text?txtsize=5&bg=bb7700&w=63&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 Sep 17 11:29:08 CEST 2017
|
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sat Oct 28 11:30:40 CEST 2017
|
||||||
|
@ -40,6 +40,7 @@ import fr.xephi.authme.command.executable.login.LoginCommand;
|
|||||||
import fr.xephi.authme.command.executable.logout.LogoutCommand;
|
import fr.xephi.authme.command.executable.logout.LogoutCommand;
|
||||||
import fr.xephi.authme.command.executable.register.RegisterCommand;
|
import fr.xephi.authme.command.executable.register.RegisterCommand;
|
||||||
import fr.xephi.authme.command.executable.unregister.UnregisterCommand;
|
import fr.xephi.authme.command.executable.unregister.UnregisterCommand;
|
||||||
|
import fr.xephi.authme.command.executable.verification.VerificationCommand;
|
||||||
import fr.xephi.authme.permission.AdminPermission;
|
import fr.xephi.authme.permission.AdminPermission;
|
||||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||||
import fr.xephi.authme.permission.PlayerPermission;
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
@ -136,13 +137,24 @@ public class CommandInitializer {
|
|||||||
CommandDescription captchaBase = CommandDescription.builder()
|
CommandDescription captchaBase = CommandDescription.builder()
|
||||||
.parent(null)
|
.parent(null)
|
||||||
.labels("captcha")
|
.labels("captcha")
|
||||||
.description("Captcha Command")
|
.description("Captcha command")
|
||||||
.detailedDescription("Captcha command for AuthMeReloaded.")
|
.detailedDescription("Captcha command for AuthMeReloaded.")
|
||||||
.withArgument("captcha", "The Captcha", false)
|
.withArgument("captcha", "The Captcha", false)
|
||||||
.permission(PlayerPermission.CAPTCHA)
|
.permission(PlayerPermission.CAPTCHA)
|
||||||
.executableCommand(CaptchaCommand.class)
|
.executableCommand(CaptchaCommand.class)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
// Register the base verification code command
|
||||||
|
CommandDescription verificationBase = CommandDescription.builder()
|
||||||
|
.parent(null)
|
||||||
|
.labels("verification")
|
||||||
|
.description("Verification command")
|
||||||
|
.detailedDescription("Command to complete the verification process for AuthMeReloaded.")
|
||||||
|
.withArgument("code", "The code", false)
|
||||||
|
.permission(PlayerPermission.VERIFICATION_CODE)
|
||||||
|
.executableCommand(VerificationCommand.class)
|
||||||
|
.register();
|
||||||
|
|
||||||
List<CommandDescription> baseCommands = ImmutableList.of(
|
List<CommandDescription> baseCommands = ImmutableList.of(
|
||||||
authMeBase,
|
authMeBase,
|
||||||
emailBase,
|
emailBase,
|
||||||
@ -151,7 +163,8 @@ public class CommandInitializer {
|
|||||||
registerBase,
|
registerBase,
|
||||||
unregisterBase,
|
unregisterBase,
|
||||||
changePasswordBase,
|
changePasswordBase,
|
||||||
captchaBase);
|
captchaBase,
|
||||||
|
verificationBase);
|
||||||
|
|
||||||
setHelpOnAllBases(baseCommands);
|
setHelpOnAllBases(baseCommands);
|
||||||
commands = baseCommands;
|
commands = baseCommands;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fr.xephi.authme.command.executable.changepassword;
|
package fr.xephi.authme.command.executable.changepassword;
|
||||||
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
@ -29,17 +30,28 @@ public class ChangePasswordCommand extends PlayerCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
String oldPassword = arguments.get(0);
|
|
||||||
String newPassword = arguments.get(1);
|
|
||||||
|
|
||||||
String name = player.getName().toLowerCase();
|
String name = player.getName().toLowerCase();
|
||||||
|
|
||||||
if (!playerCache.isAuthenticated(name)) {
|
if (!playerCache.isAuthenticated(name)) {
|
||||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the user has been verified or not
|
||||||
|
if (codeManager.isVerificationRequired(player)) {
|
||||||
|
codeManager.codeExistOrGenerateNew(name);
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String oldPassword = arguments.get(0);
|
||||||
|
String newPassword = arguments.get(1);
|
||||||
|
|
||||||
// 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()) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package fr.xephi.authme.command.executable.email;
|
package fr.xephi.authme.command.executable.email;
|
||||||
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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;
|
||||||
@ -16,11 +18,24 @@ public class ChangeEmailCommand extends PlayerCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private CommonService commonService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
|
final String playerName = player.getName();
|
||||||
|
// Check if the user has been verified or not
|
||||||
|
if (codeManager.isVerificationRequired(player)) {
|
||||||
|
codeManager.codeExistOrGenerateNew(playerName);
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String playerMailOld = arguments.get(0);
|
String playerMailOld = arguments.get(0);
|
||||||
String playerMailNew = arguments.get(1);
|
String playerMailNew = arguments.get(1);
|
||||||
|
|
||||||
management.performChangeEmail(player, playerMailOld, playerMailNew);
|
management.performChangeEmail(player, playerMailOld, playerMailNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fr.xephi.authme.command.executable.unregister;
|
package fr.xephi.authme.command.executable.unregister;
|
||||||
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
@ -24,6 +25,9 @@ public class UnregisterCommand extends PlayerCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
String playerPass = arguments.get(0);
|
String playerPass = arguments.get(0);
|
||||||
@ -35,6 +39,13 @@ public class UnregisterCommand extends PlayerCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the user has been verified or not
|
||||||
|
if (codeManager.isVerificationRequired(player)) {
|
||||||
|
codeManager.codeExistOrGenerateNew(playerName);
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Unregister the player
|
// Unregister the player
|
||||||
management.performUnregister(player, playerPass);
|
management.performUnregister(player, playerPass);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package fr.xephi.authme.command.executable.verification;
|
||||||
|
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to complete the email verification process.
|
||||||
|
*/
|
||||||
|
public class VerificationCommand extends PlayerCommand {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private CommonService commonService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
|
final String playerName = player.getName();
|
||||||
|
|
||||||
|
if (!codeManager.canSendMail()) {
|
||||||
|
ConsoleLogger.warning("Mail API is not set");
|
||||||
|
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codeManager.isVerificationRequired(player)) {
|
||||||
|
if (codeManager.isCodeRequired(playerName)) {
|
||||||
|
if (codeManager.checkCode(playerName, arguments.get(0))) {
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_VERIFIED);
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.INCORRECT_VERIFICATION_CODE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_EXPIRED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (codeManager.hasEmail(playerName)) {
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_ALREADY_VERIFIED);
|
||||||
|
} else {
|
||||||
|
commonService.send(player, MessageKey.VERIFICATION_CODE_EMAIL_NEEDED);
|
||||||
|
commonService.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageKey getArgumentsMismatchMessage() {
|
||||||
|
return MessageKey.USAGE_VERIFICATION_CODE;
|
||||||
|
}
|
||||||
|
}
|
189
src/main/java/fr/xephi/authme/data/VerificationCodeManager.java
Normal file
189
src/main/java/fr/xephi/authme/data/VerificationCodeManager.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package fr.xephi.authme.data;
|
||||||
|
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSourceResult;
|
||||||
|
import fr.xephi.authme.initialization.HasCleanup;
|
||||||
|
import fr.xephi.authme.initialization.SettingsDependent;
|
||||||
|
import fr.xephi.authme.mail.EmailService;
|
||||||
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import fr.xephi.authme.util.RandomStringUtils;
|
||||||
|
import fr.xephi.authme.util.Utils;
|
||||||
|
import fr.xephi.authme.util.expiring.ExpiringMap;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
||||||
|
|
||||||
|
private final EmailService emailService;
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final PermissionsManager permissionsManager;
|
||||||
|
|
||||||
|
private final ExpiringMap<String, String> verificationCodes;
|
||||||
|
private final Set<String> verifiedPlayers;
|
||||||
|
|
||||||
|
private boolean canSendMail;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
VerificationCodeManager(Settings settings, DataSource dataSource, EmailService emailService,
|
||||||
|
PermissionsManager permissionsManager) {
|
||||||
|
this.emailService = emailService;
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.permissionsManager = permissionsManager;
|
||||||
|
verifiedPlayers = new HashSet<>();
|
||||||
|
long countTimeout = settings.getProperty(SecuritySettings.VERIFICATION_CODE_EXPIRATION_MINUTES);
|
||||||
|
verificationCodes = new ExpiringMap<>(countTimeout, TimeUnit.MINUTES);
|
||||||
|
reload(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if it is possible to send emails
|
||||||
|
*
|
||||||
|
* @return true if the service is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean canSendMail() {
|
||||||
|
return canSendMail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given player is able to verify his identity
|
||||||
|
*
|
||||||
|
* @param player the player to verify
|
||||||
|
* @return true if the player has not been verified yet, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isVerificationRequired(Player player) {
|
||||||
|
final String name = player.getName();
|
||||||
|
return canSendMail
|
||||||
|
&& !isPlayerVerified(name)
|
||||||
|
&& permissionsManager.hasPermission(player, PlayerPermission.VERIFICATION_CODE)
|
||||||
|
&& hasEmail(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given player is required to verify his identity through a command
|
||||||
|
*
|
||||||
|
* @param name the name of the player to verify
|
||||||
|
* @return true if the player has an existing code and has not been verified yet, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isCodeRequired(String name) {
|
||||||
|
return canSendMail && hasCode(name) && !isPlayerVerified(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given player has been verified or not
|
||||||
|
*
|
||||||
|
* @param name the name of the player to verify
|
||||||
|
* @return true if the player has been verified, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isPlayerVerified(String name) {
|
||||||
|
return verifiedPlayers.contains(name.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a code exists for the player
|
||||||
|
*
|
||||||
|
* @param name the name of the player to verify
|
||||||
|
* @return true if the code exists, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean hasCode(String name) {
|
||||||
|
return (verificationCodes.get(name.toLowerCase()) != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given player is able to receive emails
|
||||||
|
*
|
||||||
|
* @param name the name of the player to verify
|
||||||
|
* @return true if the player is able to receive emails, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean hasEmail(String name) {
|
||||||
|
boolean result = false;
|
||||||
|
DataSourceResult<String> emailResult = dataSource.getEmail(name);
|
||||||
|
if (emailResult.playerExists()) {
|
||||||
|
final String email = emailResult.getValue();
|
||||||
|
if (!Utils.isEmailEmpty(email)) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a code exists for the player or generates and saves a new one.
|
||||||
|
*
|
||||||
|
* @param name the player's name
|
||||||
|
*/
|
||||||
|
public void codeExistOrGenerateNew(String name) {
|
||||||
|
if (!hasCode(name)) {
|
||||||
|
generateCode(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a code for the player and returns it.
|
||||||
|
*
|
||||||
|
* @param name the name of the player to generate a code for
|
||||||
|
*/
|
||||||
|
private void generateCode(String name) {
|
||||||
|
DataSourceResult<String> emailResult = dataSource.getEmail(name);
|
||||||
|
if (emailResult.playerExists()) {
|
||||||
|
final String email = emailResult.getValue();
|
||||||
|
if (!Utils.isEmailEmpty(email)) {
|
||||||
|
String code = RandomStringUtils.generateNum(6); // 6 digits code
|
||||||
|
verificationCodes.put(name.toLowerCase(), code);
|
||||||
|
emailService.sendVerificationMail(name, email, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the given code against the existing one.
|
||||||
|
*
|
||||||
|
* @param name the name of the player to check
|
||||||
|
* @param code the supplied code
|
||||||
|
* @return true if the code matches, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean checkCode(String name, String code) {
|
||||||
|
boolean correct = false;
|
||||||
|
if (code.equals(verificationCodes.get(name.toLowerCase()))) {
|
||||||
|
verify(name);
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
return correct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the user to the set of verified users
|
||||||
|
*
|
||||||
|
* @param name the name of the player to generate a code for
|
||||||
|
*/
|
||||||
|
public void verify(String name){
|
||||||
|
verifiedPlayers.add(name.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the user from the set of verified users
|
||||||
|
*
|
||||||
|
* @param name the name of the player to generate a code for
|
||||||
|
*/
|
||||||
|
public void unverify(String name){
|
||||||
|
verifiedPlayers.remove(name.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload(Settings settings) {
|
||||||
|
canSendMail = emailService.hasAllInformation();
|
||||||
|
long countTimeout = settings.getProperty(SecuritySettings.VERIFICATION_CODE_EXPIRATION_MINUTES);
|
||||||
|
verificationCodes.setExpiration(countTimeout, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performCleanup() {
|
||||||
|
verificationCodes.removeExpiredEntries();
|
||||||
|
}
|
||||||
|
}
|
@ -67,7 +67,7 @@ public class EmailService {
|
|||||||
File file = null;
|
File file = null;
|
||||||
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
if (settings.getProperty(EmailSettings.PASSWORD_AS_IMAGE)) {
|
||||||
try {
|
try {
|
||||||
file = generateImage(name, newPass);
|
file = generatePasswordImage(name, newPass);
|
||||||
mailText = embedImageIntoEmailContent(file, email, mailText);
|
mailText = embedImageIntoEmailContent(file, email, mailText);
|
||||||
} catch (IOException | EmailException e) {
|
} catch (IOException | EmailException e) {
|
||||||
ConsoleLogger.logException(
|
ConsoleLogger.logException(
|
||||||
@ -80,6 +80,33 @@ public class EmailService {
|
|||||||
return couldSendEmail;
|
return couldSendEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an email to the user with the temporary verification code.
|
||||||
|
*
|
||||||
|
* @param name the name of the player
|
||||||
|
* @param mailAddress the player's email
|
||||||
|
* @param code the verification code
|
||||||
|
* @return true if email could be sent, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean sendVerificationMail(String name, String mailAddress, String code) {
|
||||||
|
if (!hasAllInformation()) {
|
||||||
|
ConsoleLogger.warning("Cannot send verification email: not all email settings are complete");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HtmlEmail email;
|
||||||
|
try {
|
||||||
|
email = sendMailSsl.initializeMail(mailAddress);
|
||||||
|
} catch (EmailException e) {
|
||||||
|
ConsoleLogger.logException("Failed to create verification email with the given settings:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String mailText = replaceTagsForVerificationEmail(settings.getVerificationEmailMessage(), name, code,
|
||||||
|
settings.getProperty(SecuritySettings.VERIFICATION_CODE_EXPIRATION_MINUTES));
|
||||||
|
return sendMailSsl.sendEmail(mailText, email);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an email to the user with a recovery code for the password recovery process.
|
* Sends an email to the user with a recovery code for the password recovery process.
|
||||||
*
|
*
|
||||||
@ -102,7 +129,7 @@ public class EmailService {
|
|||||||
return sendMailSsl.sendEmail(message, htmlEmail);
|
return sendMailSsl.sendEmail(message, htmlEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File generateImage(String name, String newPass) throws IOException {
|
private File generatePasswordImage(String name, String newPass) throws IOException {
|
||||||
ImageGenerator gen = new ImageGenerator(newPass);
|
ImageGenerator gen = new ImageGenerator(newPass);
|
||||||
File file = new File(dataFolder, 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);
|
||||||
@ -123,6 +150,14 @@ public class EmailService {
|
|||||||
.replace("<generatedpass />", newPass);
|
.replace("<generatedpass />", newPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String replaceTagsForVerificationEmail(String mailText, String name, String code, int minutesValid) {
|
||||||
|
return mailText
|
||||||
|
.replace("<playername />", name)
|
||||||
|
.replace("<servername />", serverName)
|
||||||
|
.replace("<generatedcode />", code)
|
||||||
|
.replace("<minutesvalid />", String.valueOf(minutesValid));
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -239,6 +239,36 @@ public enum MessageKey {
|
|||||||
/** An email was already sent recently. You must wait %time before you can send a new one. */
|
/** An email was already sent recently. You must wait %time before you can send a new one. */
|
||||||
EMAIL_COOLDOWN_ERROR("email_cooldown_error", "%time"),
|
EMAIL_COOLDOWN_ERROR("email_cooldown_error", "%time"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command you are trying to execute is sensitive and requires a verification!
|
||||||
|
* A verification code has been sent to your email,
|
||||||
|
* run the command "/verification [code]" to verify your identity.
|
||||||
|
*/
|
||||||
|
VERIFICATION_CODE_REQUIRED("verification_code_required"),
|
||||||
|
|
||||||
|
/** Usage: /verification <code> */
|
||||||
|
USAGE_VERIFICATION_CODE("usage_verification_code"),
|
||||||
|
|
||||||
|
/** Incorrect code, please type "/verification <code>" into the chat! */
|
||||||
|
INCORRECT_VERIFICATION_CODE("incorrect_verification_code"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Your identity has been verified!
|
||||||
|
* You can now execute every sensitive command within the current session!
|
||||||
|
*/
|
||||||
|
VERIFICATION_CODE_VERIFIED("verification_code_verified"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can already execute every sensitive command within the current session!
|
||||||
|
*/
|
||||||
|
VERIFICATION_CODE_ALREADY_VERIFIED("verification_code_already_verified"),
|
||||||
|
|
||||||
|
/** Your code has expired! Execute another sensitive command to get a new code! */
|
||||||
|
VERIFICATION_CODE_EXPIRED("verification_code_expired"),
|
||||||
|
|
||||||
|
/** To verify your identity you need to link an email address with your account! */
|
||||||
|
VERIFICATION_CODE_EMAIL_NEEDED("verification_code_email_needed"),
|
||||||
|
|
||||||
/** second */
|
/** second */
|
||||||
SECOND("second"),
|
SECOND("second"),
|
||||||
|
|
||||||
|
@ -63,7 +63,12 @@ public enum PlayerPermission implements PermissionNode {
|
|||||||
/**
|
/**
|
||||||
* Permission to use to see own other accounts.
|
* Permission to use to see own other accounts.
|
||||||
*/
|
*/
|
||||||
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts");
|
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission to use the email verification codes feature.
|
||||||
|
*/
|
||||||
|
VERIFICATION_CODE("authme.player.security.verificationcode");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The permission node.
|
* The permission node.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.process.logout;
|
package fr.xephi.authme.process.logout;
|
||||||
|
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.DataSource;
|
||||||
@ -26,6 +27,9 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SyncProcessManager syncProcessManager;
|
private SyncProcessManager syncProcessManager;
|
||||||
|
|
||||||
@ -52,6 +56,7 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
playerCache.removePlayer(name);
|
playerCache.removePlayer(name);
|
||||||
|
codeManager.unverify(name);
|
||||||
database.setUnlogged(name);
|
database.setUnlogged(name);
|
||||||
database.revokeSession(name);
|
database.revokeSession(name);
|
||||||
syncProcessManager.processSyncPlayerLogout(player);
|
syncProcessManager.processSyncPlayerLogout(player);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fr.xephi.authme.process.quit;
|
package fr.xephi.authme.process.quit;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.CacheDataSource;
|
import fr.xephi.authme.datasource.CacheDataSource;
|
||||||
@ -44,6 +45,9 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private ValidationService validationService;
|
private ValidationService validationService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
AsynchronousQuit() {
|
AsynchronousQuit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +84,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
|||||||
|
|
||||||
//always unauthenticate the player - use session only for auto logins on the same ip
|
//always unauthenticate the player - use session only for auto logins on the same ip
|
||||||
playerCache.removePlayer(name);
|
playerCache.removePlayer(name);
|
||||||
|
codeManager.unverify(name);
|
||||||
|
|
||||||
//always update the database when the player quit the game (if sessions are disabled)
|
//always update the database when the player quit the game (if sessions are disabled)
|
||||||
if (wasLoggedIn) {
|
if (wasLoggedIn) {
|
||||||
|
@ -20,6 +20,7 @@ public class Settings extends SettingsManager {
|
|||||||
|
|
||||||
private final File pluginFolder;
|
private final File pluginFolder;
|
||||||
private String passwordEmailMessage;
|
private String passwordEmailMessage;
|
||||||
|
private String verificationEmailMessage;
|
||||||
private String recoveryCodeEmailMessage;
|
private String recoveryCodeEmailMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,6 +47,15 @@ public class Settings extends SettingsManager {
|
|||||||
return passwordEmailMessage;
|
return passwordEmailMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the text for verification emails (before sensitive commands can be used).
|
||||||
|
*
|
||||||
|
* @return The email message
|
||||||
|
*/
|
||||||
|
public String getVerificationEmailMessage() {
|
||||||
|
return verificationEmailMessage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the text to use when someone requests to receive a recovery code.
|
* Return the text to use when someone requests to receive a recovery code.
|
||||||
*
|
*
|
||||||
@ -57,6 +67,7 @@ public class Settings extends SettingsManager {
|
|||||||
|
|
||||||
private void loadSettingsFromFiles() {
|
private void loadSettingsFromFiles() {
|
||||||
passwordEmailMessage = readFile("email.html");
|
passwordEmailMessage = readFile("email.html");
|
||||||
|
verificationEmailMessage = readFile("verification_code_email.html");
|
||||||
recoveryCodeEmailMessage = readFile("recovery_code_email.html");
|
recoveryCodeEmailMessage = readFile("recovery_code_email.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,10 @@ public final class SecuritySettings implements SettingsHolder {
|
|||||||
public static final Property<Boolean> USE_EMAIL_MASKING =
|
public static final Property<Boolean> USE_EMAIL_MASKING =
|
||||||
newProperty("Security.privacy.enableEmailMasking", false);
|
newProperty("Security.privacy.enableEmailMasking", false);
|
||||||
|
|
||||||
|
@Comment("Minutes after which a verification code will expire")
|
||||||
|
public static final Property<Integer> VERIFICATION_CODE_EXPIRATION_MINUTES =
|
||||||
|
newProperty("Security.privacy.verificationCodeExpiration", 10);
|
||||||
|
|
||||||
private SecuritySettings() {
|
private SecuritySettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,9 @@ public final class RandomStringUtils {
|
|||||||
|
|
||||||
private static final char[] CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
private static final char[] CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
||||||
private static final Random RANDOM = new SecureRandom();
|
private static final Random RANDOM = new SecureRandom();
|
||||||
private static final int HEX_MAX_INDEX = 16;
|
private static final int NUM_INDEX = 10;
|
||||||
private static final int LOWER_ALPHANUMERIC_INDEX = 36;
|
private static final int LOWER_ALPHANUMERIC_INDEX = 36;
|
||||||
|
private static final int HEX_MAX_INDEX = 16;
|
||||||
|
|
||||||
// Utility class
|
// Utility class
|
||||||
private RandomStringUtils() {
|
private RandomStringUtils() {
|
||||||
@ -38,6 +39,17 @@ public final class RandomStringUtils {
|
|||||||
return generateString(length, HEX_MAX_INDEX);
|
return generateString(length, HEX_MAX_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random numbers string of the given length. In other words, the generated string
|
||||||
|
* contains characters only within the range [0-9].
|
||||||
|
*
|
||||||
|
* @param length The length of the random string to generate
|
||||||
|
* @return The random numbers string
|
||||||
|
*/
|
||||||
|
public static String generateNum(int length) {
|
||||||
|
return generateString(length, NUM_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random string with digits and lowercase and uppercase letters. The result of this
|
* Generate a random string with digits and lowercase and uppercase letters. The result of this
|
||||||
* method matches the pattern [0-9a-zA-Z].
|
* method matches the pattern [0-9a-zA-Z].
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&3Моля въведе цифрите/буквите от ка
|
|||||||
wrong_captcha: '&cКода е грешен, използвайте: "/captcha THE_CAPTCHA" в чата!'
|
wrong_captcha: '&cКода е грешен, използвайте: "/captcha THE_CAPTCHA" в чата!'
|
||||||
valid_captcha: '&2Кода е валиден!'
|
valid_captcha: '&2Кода е валиден!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'секунда'
|
second: 'секунда'
|
||||||
seconds: 'секунди'
|
seconds: 'секунди'
|
||||||
|
@ -100,6 +100,15 @@ usage_captcha: '&3Para iniciar sessão você tem que resolver um código captcha
|
|||||||
wrong_captcha: '&cCaptcha errado, por favor, escreva "/captcha THE_CAPTCHA" no chat!'
|
wrong_captcha: '&cCaptcha errado, por favor, escreva "/captcha THE_CAPTCHA" no chat!'
|
||||||
valid_captcha: '&2Código Captcha resolvido corretamente!'
|
valid_captcha: '&2Código Captcha resolvido corretamente!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'segundo'
|
second: 'segundo'
|
||||||
seconds: 'segundos'
|
seconds: 'segundos'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&cPoužij: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cŠpatné opsana Captcha, pouzij prosim: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cŠpatné opsana Captcha, pouzij prosim: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cZadaná captcha je v pořádku!'
|
valid_captcha: '&cZadaná captcha je v pořádku!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'sekundy'
|
second: 'sekundy'
|
||||||
seconds: 'sekund'
|
seconds: 'sekund'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha <th
|
|||||||
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&2Das Captcha ist korrekt!'
|
valid_captcha: '&2Das Captcha ist korrekt!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'Sekunde'
|
second: 'Sekunde'
|
||||||
seconds: 'Sekunden'
|
seconds: 'Sekunden'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3To login you have to solve a captcha code, please use the comm
|
|||||||
wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!'
|
wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!'
|
||||||
valid_captcha: '&2Captcha code solved correctly!'
|
valid_captcha: '&2Captcha code solved correctly!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'second'
|
second: 'second'
|
||||||
seconds: 'seconds'
|
seconds: 'seconds'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Ensaluti vi devas solvi captcha kodo, bonvolu uzi la komando:
|
|||||||
wrong_captcha: '&cMalĝusta captcha, bonvolu tajpi "/captcha THE_CAPTCHA" en la babilejo!'
|
wrong_captcha: '&cMalĝusta captcha, bonvolu tajpi "/captcha THE_CAPTCHA" en la babilejo!'
|
||||||
valid_captcha: '&2Captcha kodo solvita ĝuste!'
|
valid_captcha: '&2Captcha kodo solvita ĝuste!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'sekundo'
|
second: 'sekundo'
|
||||||
seconds: 'sekundoj'
|
seconds: 'sekundoj'
|
||||||
|
@ -99,6 +99,15 @@ usage_captcha: '&cUso: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cCaptcha incorrecto, por favor usa: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cCaptcha incorrecto, por favor usa: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&c¡ Captcha ingresado correctamente !'
|
valid_captcha: '&c¡ Captcha ingresado correctamente !'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'segundo'
|
second: 'segundo'
|
||||||
seconds: 'segundos'
|
seconds: 'segundos'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Sisselogimiseks pead lahendama captcha. Tee seda kasutades kä
|
|||||||
wrong_captcha: '&cVale captcha, kirjuta "/captcha THE_CAPTCHA" chatti!'
|
wrong_captcha: '&cVale captcha, kirjuta "/captcha THE_CAPTCHA" chatti!'
|
||||||
valid_captcha: '&2Captcha lahendatud!'
|
valid_captcha: '&2Captcha lahendatud!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'sekund'
|
second: 'sekund'
|
||||||
seconds: 'sekundit'
|
seconds: 'sekundit'
|
||||||
|
@ -96,6 +96,15 @@ recovery_email: '&cPasahitza ahaztu duzu? Erabili /email recovery <zureemaila>'
|
|||||||
# TODO wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!'
|
# TODO wrong_captcha: '&cWrong captcha, please type "/captcha THE_CAPTCHA" into the chat!'
|
||||||
# TODO valid_captcha: '&2Captcha code solved correctly!'
|
# TODO valid_captcha: '&2Captcha code solved correctly!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&cKäyttötapa: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cVäärä varmistus, käytä : /captcha THE_CAPTCHA'
|
wrong_captcha: '&cVäärä varmistus, käytä : /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cSinun varmistus onnistui.!'
|
valid_captcha: '&cSinun varmistus onnistui.!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -101,6 +101,15 @@ usage_captcha: '&cTrop de tentatives de connexion échouées, utilisez: /captcha
|
|||||||
wrong_captcha: '&cCaptcha incorrect, écrivez de nouveau: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cCaptcha incorrect, écrivez de nouveau: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&aCaptché validé! Veuillez maintenant vous connecter.'
|
valid_captcha: '&aCaptché validé! Veuillez maintenant vous connecter.'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Unités de temps
|
# Unités de temps
|
||||||
second: 'seconde'
|
second: 'seconde'
|
||||||
seconds: 'secondes'
|
seconds: 'secondes'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&cNecesitas escribir un captcha, por favor escribe: /captcha <th
|
|||||||
wrong_captcha: '&cCaptcha equivocado, por favor usa: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cCaptcha equivocado, por favor usa: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cO teu captcha é válido !'
|
valid_captcha: '&cO teu captcha é válido !'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -80,7 +80,6 @@ email_added: '&2Az email címed rögzítése sikeresen megtörtént!'
|
|||||||
email_confirm: '&cKérlek, ellenőrízd az email címedet!'
|
email_confirm: '&cKérlek, ellenőrízd az email címedet!'
|
||||||
email_changed: '&2Az email cím cseréje sikeresen megtörtént!'
|
email_changed: '&2Az email cím cseréje sikeresen megtörtént!'
|
||||||
email_send: '&2A jelszó visszaállításhoz szükséges emailt elküldtük! Ellenőrizd a leveleidet!'
|
email_send: '&2A jelszó visszaállításhoz szükséges emailt elküldtük! Ellenőrizd a leveleidet!'
|
||||||
email_exists: '&cA visszaállító emailt elküldtük! Hiba esetén újra kérheted az alábbi parancs segítségével:'
|
|
||||||
email_show: '&2A jelenlegi email-ed a következő: &f%email'
|
email_show: '&2A jelenlegi email-ed a következő: &f%email'
|
||||||
incomplete_email_settings: 'Hiba: nem lett beállítva az összes szükséges beállítás az email küldéshez. Vedd fel a kapcsolatot egy adminnal.'
|
incomplete_email_settings: 'Hiba: nem lett beállítva az összes szükséges beállítás az email küldéshez. Vedd fel a kapcsolatot egy adminnal.'
|
||||||
email_already_used: '&4Ez az email cím már használatban van!'
|
email_already_used: '&4Ez az email cím már használatban van!'
|
||||||
@ -88,6 +87,7 @@ email_send_failure: 'Nem sikerült elküldeni az emailt. Lépj kapcsolatba egy a
|
|||||||
show_no_email: '&2Ehhez a felhasználóhoz jelenleg még nincs email hozzárendelve.'
|
show_no_email: '&2Ehhez a felhasználóhoz jelenleg még nincs email hozzárendelve.'
|
||||||
add_email: '&3Kérlek, rendeld hozzá a felhasználódhoz az email címedet "&7/email add <email címed> <email címed ismét>&3".'
|
add_email: '&3Kérlek, rendeld hozzá a felhasználódhoz az email címedet "&7/email add <email címed> <email címed ismét>&3".'
|
||||||
recovery_email: '&3Ha elfelejtetted a jelszavad, használd az "&7/email recovery <regisztrált email címed>&3".'
|
recovery_email: '&3Ha elfelejtetted a jelszavad, használd az "&7/email recovery <regisztrált email címed>&3".'
|
||||||
|
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
|
||||||
email_cooldown_error: '&cEgy emailt már kiküldtünk. Következő email küldése előtt várnod kell: %time.'
|
email_cooldown_error: '&cEgy emailt már kiküldtünk. Következő email küldése előtt várnod kell: %time.'
|
||||||
|
|
||||||
# Captcha
|
# Captcha
|
||||||
@ -95,6 +95,15 @@ usage_captcha: '&3A bejelentkezéshez CAPTCHA szükséges, kérlek, használd a
|
|||||||
wrong_captcha: '&cHibás CAPTCHA, kérlek, írd be a következő parancsot: "&7/captcha THE_CAPTCHA&c"!'
|
wrong_captcha: '&cHibás CAPTCHA, kérlek, írd be a következő parancsot: "&7/captcha THE_CAPTCHA&c"!'
|
||||||
valid_captcha: '&2A CAPTCHA sikeresen feloldva!'
|
valid_captcha: '&2A CAPTCHA sikeresen feloldva!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'másodperc'
|
second: 'másodperc'
|
||||||
seconds: 'másodperc'
|
seconds: 'másodperc'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&3Kamu harus menyelesaikan kode captcha untuk login, silahkan gu
|
|||||||
wrong_captcha: '&cCaptcha salah, gunakan command "/captcha THE_CAPTCHA" pada chat!'
|
wrong_captcha: '&cCaptcha salah, gunakan command "/captcha THE_CAPTCHA" pada chat!'
|
||||||
valid_captcha: '&2Kode captcha terselesaikan!'
|
valid_captcha: '&2Kode captcha terselesaikan!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -97,6 +97,15 @@ usage_captcha: '&3Per poterti autenticare devi risolvere un captcha, per favore
|
|||||||
wrong_captcha: '&cCaptcha sbagliato, per favore riprova scrivendo: "/captcha THE_CAPTCHA" in chat!'
|
wrong_captcha: '&cCaptcha sbagliato, per favore riprova scrivendo: "/captcha THE_CAPTCHA" in chat!'
|
||||||
valid_captcha: '&2Il captcha inserito è valido!'
|
valid_captcha: '&2Il captcha inserito è valido!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Unità di tempo
|
# Unità di tempo
|
||||||
second: 'secondo'
|
second: 'secondo'
|
||||||
seconds: 'secondi'
|
seconds: 'secondi'
|
||||||
|
@ -34,7 +34,6 @@ tempban_max_logins: '&c너무 많이 로그인에 실패하여 잠시 서버에
|
|||||||
max_reg: '&c당신은 가입할 수 있는 계정 한도를 초과했습니다 (%reg_count/%max_acc %reg_names)!'
|
max_reg: '&c당신은 가입할 수 있는 계정 한도를 초과했습니다 (%reg_count/%max_acc %reg_names)!'
|
||||||
no_perm: '&4이 작업을 수행할 수 있는 권한이 없습니다!'
|
no_perm: '&4이 작업을 수행할 수 있는 권한이 없습니다!'
|
||||||
error: '&4예기치 않은 오류가 발생했습니다, 관리자에게 알려주세요!'
|
error: '&4예기치 않은 오류가 발생했습니다, 관리자에게 알려주세요!'
|
||||||
unsafe_spawn: '&c마지막으로 접속한 위치가 안전하지 않습니다, 이 세계의 스폰 지점으로 텔레포트 됩니다.'
|
|
||||||
kick_forvip: '&3서버가 꽉 차있을땐 VIP 플레이어만 접속이 가능합니다!'
|
kick_forvip: '&3서버가 꽉 차있을땐 VIP 플레이어만 접속이 가능합니다!'
|
||||||
|
|
||||||
# AntiBot
|
# AntiBot
|
||||||
@ -48,7 +47,11 @@ accounts_owned_self: '%count 개의 계정을 소유하고 있습니다:'
|
|||||||
accounts_owned_other: '플레이어 %name 는 %count 개의 계정을 소유하고 있습니다:'
|
accounts_owned_other: '플레이어 %name 는 %count 개의 계정을 소유하고 있습니다:'
|
||||||
two_factor_create: '&2당신의 비밀 코드는 %code 입니다. %url 에서 스캔할 수 있습니다'
|
two_factor_create: '&2당신의 비밀 코드는 %code 입니다. %url 에서 스캔할 수 있습니다'
|
||||||
recovery_code_sent: '비밀번호 재설정을 위한 복구 코드가 이메일로 전송되었습니다.'
|
recovery_code_sent: '비밀번호 재설정을 위한 복구 코드가 이메일로 전송되었습니다.'
|
||||||
|
# TODO: Missing tags %count
|
||||||
recovery_code_incorrect: '복구 코드가 올바르지 않습니다! "/email recovery [이메일 주소]"를 이용하여 새로 생성하세요'
|
recovery_code_incorrect: '복구 코드가 올바르지 않습니다! "/email recovery [이메일 주소]"를 이용하여 새로 생성하세요'
|
||||||
|
# TODO recovery_tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.'
|
||||||
|
# TODO recovery_code_correct: 'Recovery code entered correctly!'
|
||||||
|
# TODO recovery_change_password: 'Please use the command /email setpassword <new password> to change your password immediately.'
|
||||||
vb_nonActiv: '&c계정이 아직 활성화되지 않았습니다, 이메일을 확인해보세요!'
|
vb_nonActiv: '&c계정이 아직 활성화되지 않았습니다, 이메일을 확인해보세요!'
|
||||||
usage_unreg: '&c사용법: /unregister <비밀번호>'
|
usage_unreg: '&c사용법: /unregister <비밀번호>'
|
||||||
pwd_changed: '&2비밀번호가 변경되었습니다!'
|
pwd_changed: '&2비밀번호가 변경되었습니다!'
|
||||||
@ -82,7 +85,6 @@ email_added: '&2계정에 이메일 주소를 추가했습니다!'
|
|||||||
email_confirm: '&c이메일 주소를 확인해주세요!'
|
email_confirm: '&c이메일 주소를 확인해주세요!'
|
||||||
email_changed: '&2이메일 주소가 변경되었습니다!'
|
email_changed: '&2이메일 주소가 변경되었습니다!'
|
||||||
email_send: '&2복구 이메일을 보냈습니다! 메일함을 확인해보세요!'
|
email_send: '&2복구 이메일을 보냈습니다! 메일함을 확인해보세요!'
|
||||||
email_exists: '&c복구 이메일을 이미 보냈습니다! 아래 명령어를 사용하여 취소하고 다시 보낼 수 있습니다:'
|
|
||||||
email_show: '&2현재 이메일 주소: &f%email'
|
email_show: '&2현재 이메일 주소: &f%email'
|
||||||
incomplete_email_settings: '오류: 메일을 보내기 위해 필요한 설정이 되어 있지 않습니다. 관리자에게 알려주세요.'
|
incomplete_email_settings: '오류: 메일을 보내기 위해 필요한 설정이 되어 있지 않습니다. 관리자에게 알려주세요.'
|
||||||
email_already_used: '&4이메일 주소가 이미 사용 중입니다.'
|
email_already_used: '&4이메일 주소가 이미 사용 중입니다.'
|
||||||
@ -90,8 +92,29 @@ email_send_failure: '이메일을 보낼 수 없습니다. 관리자에게 알
|
|||||||
show_no_email: '&2현재 이 계정과 연결된 이메일 주소가 없습니다.'
|
show_no_email: '&2현재 이 계정과 연결된 이메일 주소가 없습니다.'
|
||||||
add_email: '&3다음 명령어로 계정에 이메일 주소를 추가하세요: /email add <이메일 주소> <이메일 주소 확인>'
|
add_email: '&3다음 명령어로 계정에 이메일 주소를 추가하세요: /email add <이메일 주소> <이메일 주소 확인>'
|
||||||
recovery_email: '&3비밀번호를 잊으셨나요? 이 명령어를 사용해보세요: /email recovery <이메일 주소>'
|
recovery_email: '&3비밀번호를 잊으셨나요? 이 명령어를 사용해보세요: /email recovery <이메일 주소>'
|
||||||
|
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
|
||||||
|
# TODO email_cooldown_error: '&cAn email was already sent recently. You must wait %time before you can send a new one.'
|
||||||
|
|
||||||
# Captcha
|
# Captcha
|
||||||
usage_captcha: '&3로그인 하려면 CAPTCHA 코드를 입력해야 합니다, 이 명령어를 사용하세요: /captcha <theCaptcha>'
|
usage_captcha: '&3로그인 하려면 CAPTCHA 코드를 입력해야 합니다, 이 명령어를 사용하세요: /captcha <theCaptcha>'
|
||||||
wrong_captcha: '&c잘못된 CAPTCHA 코드 입니다, "/captcha THE_CAPTCHA"을 입력해주세요!'
|
wrong_captcha: '&c잘못된 CAPTCHA 코드 입니다, "/captcha THE_CAPTCHA"을 입력해주세요!'
|
||||||
valid_captcha: '&2CAPTCHA 코드가 확인되었습니다!'
|
valid_captcha: '&2CAPTCHA 코드가 확인되었습니다!'
|
||||||
|
|
||||||
|
# Verification Code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
|
# Time units
|
||||||
|
# TODO second: 'second'
|
||||||
|
# TODO seconds: 'seconds'
|
||||||
|
# TODO minute: 'minute'
|
||||||
|
# TODO minutes: 'minutes'
|
||||||
|
# TODO hour: 'hour'
|
||||||
|
# TODO hours: 'hours'
|
||||||
|
# TODO day: 'day'
|
||||||
|
# TODO days: 'days'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&cPanaudojimas: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cNeteisinga Captcha, naudokite : /captcha THE_CAPTCHA'
|
wrong_captcha: '&cNeteisinga Captcha, naudokite : /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cJusu captcha Teisinga!'
|
valid_captcha: '&cJusu captcha Teisinga!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Om in te loggen moet je een captcha-code oplossen, gebruik het
|
|||||||
wrong_captcha: '&cVerkeerde captcha-code, typ alsjeblieft "/captcha THE_CAPTCHA" in de chat!'
|
wrong_captcha: '&cVerkeerde captcha-code, typ alsjeblieft "/captcha THE_CAPTCHA" in de chat!'
|
||||||
valid_captcha: '&2De captcha-code is geldig!'
|
valid_captcha: '&2De captcha-code is geldig!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'seconde'
|
second: 'seconde'
|
||||||
seconds: 'seconden'
|
seconds: 'seconden'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&cWpisz: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cZły kod, proszę wpisać: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cZły kod, proszę wpisać: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cTwój kod jest nieprawidłowy!'
|
valid_captcha: '&cTwój kod jest nieprawidłowy!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'sekundy'
|
second: 'sekundy'
|
||||||
seconds: 'sekund'
|
seconds: 'sekund'
|
||||||
|
@ -97,6 +97,15 @@ usage_captcha: '&cPrecisa digitar um captcha, escreva: /captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&cCaptcha errado, por favor escreva: /captcha THE_CAPTCHA'
|
wrong_captcha: '&cCaptcha errado, por favor escreva: /captcha THE_CAPTCHA'
|
||||||
valid_captcha: '&cO seu captcha é válido!'
|
valid_captcha: '&cO seu captcha é válido!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'segundo'
|
second: 'segundo'
|
||||||
seconds: 'segundos'
|
seconds: 'segundos'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Pentru a te autentifica, te rugam sa folosesti comanda "/captc
|
|||||||
wrong_captcha: '&cCodul de verificare este gresit, te rugam foloseste comanda "/captcha THE_CAPTCHA"!'
|
wrong_captcha: '&cCodul de verificare este gresit, te rugam foloseste comanda "/captcha THE_CAPTCHA"!'
|
||||||
valid_captcha: '&2Codul de verificare a fost scris corect!'
|
valid_captcha: '&2Codul de verificare a fost scris corect!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'secunda'
|
second: 'secunda'
|
||||||
seconds: 'secunde'
|
seconds: 'secunde'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Необходимо ввести текст с каптчи.
|
|||||||
wrong_captcha: '&cНеверно! Используйте «/captcha THE_CAPTCHA».'
|
wrong_captcha: '&cНеверно! Используйте «/captcha THE_CAPTCHA».'
|
||||||
valid_captcha: '&2Вы успешно решили каптчу!'
|
valid_captcha: '&2Вы успешно решили каптчу!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Единицы времени
|
# Единицы времени
|
||||||
second: 'с.'
|
second: 'с.'
|
||||||
seconds: 'с.'
|
seconds: 'с.'
|
||||||
|
@ -102,6 +102,15 @@ usage_captcha: '&3Pre prihlásenie musíš vyriešiť captcha kód, prosím pou
|
|||||||
wrong_captcha: '&cNesprávny kód captcha, prosím napíš "/captcha THE_CAPTCHA" do chatu!'
|
wrong_captcha: '&cNesprávny kód captcha, prosím napíš "/captcha THE_CAPTCHA" do chatu!'
|
||||||
valid_captcha: '&2Správne si vyriešil captcha kód!'
|
valid_captcha: '&2Správne si vyriešil captcha kód!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'sek.'
|
second: 'sek.'
|
||||||
seconds: 'sek.'
|
seconds: 'sek.'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&3Giris yapmak icin guvenlik kodunu komut yazarak girin "/captch
|
|||||||
wrong_captcha: '&cYanlis guvenlik kodu, kullanim sekli "/captcha THE_CAPTCHA" sohbete yazin!'
|
wrong_captcha: '&cYanlis guvenlik kodu, kullanim sekli "/captcha THE_CAPTCHA" sohbete yazin!'
|
||||||
valid_captcha: '&2Guvenlik kodu dogrulandi!'
|
valid_captcha: '&2Guvenlik kodu dogrulandi!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Zaman birimleri
|
# Zaman birimleri
|
||||||
second: 'saniye'
|
second: 'saniye'
|
||||||
seconds: 'saniye'
|
seconds: 'saniye'
|
||||||
|
@ -95,6 +95,15 @@ usage_captcha: '&3Для продовження доведеться ввест
|
|||||||
wrong_captcha: '&cНевірно введена капча! Спробуйте ще раз — "/captcha THE_CAPTCHA"'
|
wrong_captcha: '&cНевірно введена капча! Спробуйте ще раз — "/captcha THE_CAPTCHA"'
|
||||||
valid_captcha: '&2Капчу прийнято.'
|
valid_captcha: '&2Капчу прийнято.'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&eĐể đăng nhập vui lòng hãy nhập mã Captcha, gõ l
|
|||||||
wrong_captcha: '&cSai mã captcha, Vui lòng gõ lệnh "/captcha THE_CAPTCHA"!'
|
wrong_captcha: '&cSai mã captcha, Vui lòng gõ lệnh "/captcha THE_CAPTCHA"!'
|
||||||
valid_captcha: '&2Mã captcha đã được xác nhận!'
|
valid_captcha: '&2Mã captcha đã được xác nhận!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: 'giây'
|
second: 'giây'
|
||||||
seconds: 'giây'
|
seconds: 'giây'
|
||||||
|
@ -97,6 +97,15 @@ usage_captcha: '&8[&6玩家系统&8] &c正确用法:/captcha <theCaptcha>'
|
|||||||
wrong_captcha: '&8[&6玩家系统&8] &c错误的验证码,请输入:“/captcha THE_CAPTCHA”'
|
wrong_captcha: '&8[&6玩家系统&8] &c错误的验证码,请输入:“/captcha THE_CAPTCHA”'
|
||||||
valid_captcha: '&8[&6玩家系统&8] &c你的验证码是有效的!'
|
valid_captcha: '&8[&6玩家系统&8] &c你的验证码是有效的!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# 时间单位
|
# 时间单位
|
||||||
second: '秒'
|
second: '秒'
|
||||||
seconds: '秒'
|
seconds: '秒'
|
||||||
|
@ -99,6 +99,15 @@ usage_captcha: '&8[&6用戶系統&8] &f用法:《 /captcha <theCaptcha> 》'
|
|||||||
wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效,請使用 《 /captcha THE_CAPTCHA 》 再次輸入。'
|
wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效,請使用 《 /captcha THE_CAPTCHA 》 再次輸入。'
|
||||||
valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效 !'
|
valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效 !'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
second: '秒'
|
second: '秒'
|
||||||
seconds: '秒'
|
seconds: '秒'
|
||||||
|
@ -96,6 +96,15 @@ usage_captcha: '&3T要登錄您必須使用captcha驗證碼,請使用命令: "/c
|
|||||||
wrong_captcha: '&c驗證碼錯誤!請按T在聊天中輸入 "/captcha THE_CAPTCHA"'
|
wrong_captcha: '&c驗證碼錯誤!請按T在聊天中輸入 "/captcha THE_CAPTCHA"'
|
||||||
valid_captcha: '&2驗證碼正確!'
|
valid_captcha: '&2驗證碼正確!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -100,6 +100,15 @@ usage_captcha: '&b【AuthMe】&6請用 &c"/captcha <theCaptcha>" &6來輸入你
|
|||||||
wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼,請使用 《 /captcha THE_CAPTCHA 》 再試一次吧。'
|
wrong_captcha: '&b【AuthMe】&6錯誤的驗證碼,請使用 《 /captcha THE_CAPTCHA 》 再試一次吧。'
|
||||||
valid_captcha: '&b【AuthMe】&6驗證碼無效!'
|
valid_captcha: '&b【AuthMe】&6驗證碼無效!'
|
||||||
|
|
||||||
|
# Verification code
|
||||||
|
# TODO verification_code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
|
||||||
|
# TODO usage_verification_code: '&cUsage: /verification <code>'
|
||||||
|
# TODO incorrect_verification_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
|
||||||
|
# TODO verification_code_verified: '&2Your identity has been verified! You can now execute all commands within the current session!'
|
||||||
|
# TODO verification_code_already_verified: '&2You can already execute every sensitive command within the current session!'
|
||||||
|
# TODO verification_code_expired: '&3Your code has expired! Execute an other sensitive command to get a new code!'
|
||||||
|
# TODO verification_code_email_needed: '&3To verify your identity you need to link an email address with your account!!'
|
||||||
|
|
||||||
# Time units
|
# Time units
|
||||||
# TODO second: 'second'
|
# TODO second: 'second'
|
||||||
# TODO seconds: 'seconds'
|
# TODO seconds: 'seconds'
|
||||||
|
@ -47,8 +47,11 @@ commands:
|
|||||||
- changepass
|
- changepass
|
||||||
- cp
|
- cp
|
||||||
captcha:
|
captcha:
|
||||||
description: Captcha Command
|
description: Captcha command
|
||||||
usage: /captcha <captcha>
|
usage: /captcha <captcha>
|
||||||
|
verification:
|
||||||
|
description: Verification command
|
||||||
|
usage: /verification <code>
|
||||||
permissions:
|
permissions:
|
||||||
authme.admin.*:
|
authme.admin.*:
|
||||||
description: Gives access to all admin commands
|
description: Gives access to all admin commands
|
||||||
@ -224,6 +227,7 @@ permissions:
|
|||||||
authme.player.login: true
|
authme.player.login: true
|
||||||
authme.player.logout: true
|
authme.player.logout: true
|
||||||
authme.player.register: true
|
authme.player.register: true
|
||||||
|
authme.player.security.verificationcode: true
|
||||||
authme.player.seeownaccounts: true
|
authme.player.seeownaccounts: true
|
||||||
authme.player.unregister: true
|
authme.player.unregister: true
|
||||||
authme.player.canbeforced:
|
authme.player.canbeforced:
|
||||||
@ -263,6 +267,9 @@ permissions:
|
|||||||
authme.player.register:
|
authme.player.register:
|
||||||
description: Command permission to register.
|
description: Command permission to register.
|
||||||
default: true
|
default: true
|
||||||
|
authme.player.security.verificationcode:
|
||||||
|
description: Permission to use the email verification codes feature.
|
||||||
|
default: true
|
||||||
authme.player.seeownaccounts:
|
authme.player.seeownaccounts:
|
||||||
description: Permission to use to see own other accounts.
|
description: Permission to use to see own other accounts.
|
||||||
default: true
|
default: true
|
||||||
|
20
src/main/resources/verification_code_email.html
Normal file
20
src/main/resources/verification_code_email.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<h1>
|
||||||
|
Dear <playername />,
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This is your temporary verification code for the server <servername />:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<generatedcode />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This code will be valid for the next <minutesvalid /> mins!<br />
|
||||||
|
Use the command
|
||||||
|
/verification <generatedcode />
|
||||||
|
to complete the verification process.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
See you on <servername />!
|
||||||
|
</p>
|
@ -44,7 +44,7 @@ public class CommandInitializerTest {
|
|||||||
// It obviously doesn't make sense to test much of the concrete data
|
// It obviously doesn't make sense to test much of the concrete data
|
||||||
// that is being initialized; we just want to guarantee with this test
|
// that is being initialized; we just want to guarantee with this test
|
||||||
// that data is indeed being initialized and we take a few "probes"
|
// that data is indeed being initialized and we take a few "probes"
|
||||||
assertThat(commands, hasSize(8));
|
assertThat(commands, hasSize(9));
|
||||||
assertThat(commandsIncludeLabel(commands, "authme"), equalTo(true));
|
assertThat(commandsIncludeLabel(commands, "authme"), equalTo(true));
|
||||||
assertThat(commandsIncludeLabel(commands, "register"), equalTo(true));
|
assertThat(commandsIncludeLabel(commands, "register"), equalTo(true));
|
||||||
assertThat(commandsIncludeLabel(commands, "help"), equalTo(false));
|
assertThat(commandsIncludeLabel(commands, "help"), equalTo(false));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.command.executable.changepassword;
|
package fr.xephi.authme.command.executable.changepassword;
|
||||||
|
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
@ -40,11 +41,14 @@ public class ChangePasswordCommandTest {
|
|||||||
private ChangePasswordCommand command;
|
private ChangePasswordCommand command;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CommonService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ValidationService validationService;
|
private ValidationService validationService;
|
||||||
|
|
||||||
@ -72,23 +76,24 @@ public class ChangePasswordCommandTest {
|
|||||||
command.executeCommand(sender, Arrays.asList("pass", "pass"));
|
command.executeCommand(sender, Arrays.asList("pass", "pass"));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(commandService).send(sender, MessageKey.NOT_LOGGED_IN);
|
verify(commonService).send(sender, MessageKey.NOT_LOGGED_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldRejectInvalidPassword() {
|
public void shouldRejectInvalidPassword() {
|
||||||
// given
|
// given
|
||||||
CommandSender sender = initPlayerWithName("abc12", true);
|
Player sender = initPlayerWithName("abc12", true);
|
||||||
String password = "newPW";
|
String password = "newPW";
|
||||||
given(validationService.validatePassword(password, "abc12"))
|
given(validationService.validatePassword(password, "abc12")).willReturn(new ValidationResult(MessageKey.INVALID_PASSWORD_LENGTH));
|
||||||
.willReturn(new ValidationResult(MessageKey.INVALID_PASSWORD_LENGTH));
|
given(codeManager.isVerificationRequired(sender)).willReturn(false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
command.executeCommand(sender, Arrays.asList("tester", password));
|
command.executeCommand(sender, Arrays.asList("tester", password));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(validationService).validatePassword(password, "abc12");
|
verify(validationService).validatePassword(password, "abc12");
|
||||||
verify(commandService).send(sender, MessageKey.INVALID_PASSWORD_LENGTH, new String[0]);
|
verify(commonService).send(sender, MessageKey.INVALID_PASSWORD_LENGTH, new String[0]);
|
||||||
|
verify(codeManager).isVerificationRequired(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -98,14 +103,16 @@ public class ChangePasswordCommandTest {
|
|||||||
String newPass = "abc123";
|
String newPass = "abc123";
|
||||||
Player player = initPlayerWithName("parker", true);
|
Player player = initPlayerWithName("parker", true);
|
||||||
given(validationService.validatePassword("abc123", "parker")).willReturn(new ValidationResult());
|
given(validationService.validatePassword("abc123", "parker")).willReturn(new ValidationResult());
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
command.executeCommand(player, Arrays.asList(oldPass, newPass));
|
command.executeCommand(player, Arrays.asList(oldPass, newPass));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(validationService).validatePassword(newPass, "parker");
|
verify(validationService).validatePassword(newPass, "parker");
|
||||||
verify(commandService, never()).send(eq(player), any(MessageKey.class));
|
verify(commonService, never()).send(eq(player), any(MessageKey.class));
|
||||||
verify(management).performPasswordChange(player, oldPass, newPass);
|
verify(management).performPasswordChange(player, oldPass, newPass);
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package fr.xephi.authme.command.executable.email;
|
package fr.xephi.authme.command.executable.email;
|
||||||
|
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.command.BlockCommandSender;
|
import org.bukkit.command.BlockCommandSender;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -16,9 +18,11 @@ import java.util.Collections;
|
|||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link ChangeEmailCommand}.
|
* Test for {@link ChangeEmailCommand}.
|
||||||
@ -32,6 +36,12 @@ public class ChangeEmailCommandTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CommonService commonService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldRejectNonPlayerSender() {
|
public void shouldRejectNonPlayerSender() {
|
||||||
@ -45,16 +55,34 @@ public class ChangeEmailCommandTest {
|
|||||||
verifyZeroInteractions(management);
|
verifyZeroInteractions(management);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldStopIfVerificationIsRequired() {
|
||||||
|
// given
|
||||||
|
String name = "Testeroni";
|
||||||
|
Player player = initPlayerWithName(name);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Arrays.asList("mail@example.org", "otherMail@example.com"));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).codeExistOrGenerateNew(name);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
|
verifyZeroInteractions(management);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldForwardData() {
|
public void shouldForwardData() {
|
||||||
// given
|
// given
|
||||||
Player sender = mock(Player.class);
|
Player sender = initPlayerWithName("AmATest");
|
||||||
|
given(codeManager.isVerificationRequired(sender)).willReturn(false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
command.executeCommand(sender, Arrays.asList("new.mail@example.org", "old_mail@example.org"));
|
command.executeCommand(sender, Arrays.asList("new.mail@example.org", "old_mail@example.org"));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(management).performChangeEmail(sender, "new.mail@example.org", "old_mail@example.org");
|
verify(management).performChangeEmail(sender, "new.mail@example.org", "old_mail@example.org");
|
||||||
|
verify(codeManager).isVerificationRequired(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -62,4 +90,10 @@ public class ChangeEmailCommandTest {
|
|||||||
// given / when / then
|
// given / when / then
|
||||||
assertThat(command.getArgumentsMismatchMessage(), equalTo(MessageKey.USAGE_CHANGE_EMAIL));
|
assertThat(command.getArgumentsMismatchMessage(), equalTo(MessageKey.USAGE_CHANGE_EMAIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Player initPlayerWithName(String name) {
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
when(player.getName()).thenReturn(name);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.command.executable.unregister;
|
package fr.xephi.authme.command.executable.unregister;
|
||||||
|
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
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.process.Management;
|
import fr.xephi.authme.process.Management;
|
||||||
@ -17,11 +18,11 @@ import java.util.Collections;
|
|||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
|
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link UnregisterCommand}.
|
* Test for {@link UnregisterCommand}.
|
||||||
@ -36,11 +37,14 @@ public class UnregisterCommandTest {
|
|||||||
private Management management;
|
private Management management;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CommonService commandService;
|
private CommonService commonService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldCatchUnauthenticatedUser() {
|
public void shouldCatchUnauthenticatedUser() {
|
||||||
// given
|
// given
|
||||||
@ -55,7 +59,26 @@ public class UnregisterCommandTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(playerCache).isAuthenticated(name);
|
verify(playerCache).isAuthenticated(name);
|
||||||
verify(commandService).send(player, MessageKey.NOT_LOGGED_IN);
|
verify(commonService).send(player, MessageKey.NOT_LOGGED_IN);
|
||||||
|
verifyZeroInteractions(management);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldStopForMissingVerificationCode() {
|
||||||
|
// given
|
||||||
|
String name = "asldjf";
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
given(player.getName()).willReturn(name);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList("blergh"));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache).isAuthenticated(name);
|
||||||
|
verify(codeManager).codeExistOrGenerateNew(name);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
verifyZeroInteractions(management);
|
verifyZeroInteractions(management);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +90,7 @@ public class UnregisterCommandTest {
|
|||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
given(player.getName()).willReturn(name);
|
given(player.getName()).willReturn(name);
|
||||||
given(playerCache.isAuthenticated(name)).willReturn(true);
|
given(playerCache.isAuthenticated(name)).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
command.executeCommand(player, Collections.singletonList(password));
|
command.executeCommand(player, Collections.singletonList(password));
|
||||||
@ -74,6 +98,7 @@ public class UnregisterCommandTest {
|
|||||||
// then
|
// then
|
||||||
verify(playerCache).isAuthenticated(name);
|
verify(playerCache).isAuthenticated(name);
|
||||||
verify(management).performUnregister(player, password);
|
verify(management).performUnregister(player, password);
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,161 @@
|
|||||||
|
package fr.xephi.authme.command.executable.verification;
|
||||||
|
|
||||||
|
import fr.xephi.authme.data.VerificationCodeManager;
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link VerificationCommand}.
|
||||||
|
*/
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class VerificationCommandTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private VerificationCommand command;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CommonService commonService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private VerificationCodeManager codeManager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldDetectIfMailHasASetup() {
|
||||||
|
// given
|
||||||
|
String name = "Alligator";
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(false);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList("code"));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(commonService).send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRequireAndAcceptCode() {
|
||||||
|
// given
|
||||||
|
String name = "Duck";
|
||||||
|
String code = "123932";
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(true);
|
||||||
|
given(codeManager.isCodeRequired(name)).willReturn(true);
|
||||||
|
given(codeManager.checkCode(name, code)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList(code));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
|
verify(codeManager).isCodeRequired(name);
|
||||||
|
verify(codeManager).checkCode(name, code);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_VERIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRejectCode() {
|
||||||
|
// given
|
||||||
|
String name = "Spider";
|
||||||
|
String code = "98345222"; // more than 6 digits
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(true);
|
||||||
|
given(codeManager.isCodeRequired(name)).willReturn(true);
|
||||||
|
given(codeManager.checkCode(name, code)).willReturn(false);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList(code));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
|
verify(codeManager).isCodeRequired(name);
|
||||||
|
verify(codeManager).checkCode(name, code);
|
||||||
|
verify(commonService).send(player, MessageKey.INCORRECT_VERIFICATION_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRejectVerificationDueToExpiration() {
|
||||||
|
// given
|
||||||
|
String name = "Dog";
|
||||||
|
String code = "131552";
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(true);
|
||||||
|
given(codeManager.isCodeRequired(name)).willReturn(false);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList(code));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
|
verify(codeManager).isCodeRequired(name);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_EXPIRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRejectVerificationDueToVerifiedIdentity() {
|
||||||
|
// given
|
||||||
|
String name = "Cow";
|
||||||
|
String code = "973583";
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(false);
|
||||||
|
given(codeManager.hasEmail(name)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList(code));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
|
verify(codeManager).hasEmail(name);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_ALREADY_VERIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRejectVerificationDueToUndefinedEmail() {
|
||||||
|
// given
|
||||||
|
String name = "Frog";
|
||||||
|
String code = "774543";
|
||||||
|
Player player = mockPlayerWithName(name);
|
||||||
|
given(codeManager.canSendMail()).willReturn(true);
|
||||||
|
given(codeManager.isVerificationRequired(player)).willReturn(false);
|
||||||
|
given(codeManager.hasEmail(name)).willReturn(false);
|
||||||
|
|
||||||
|
// when
|
||||||
|
command.executeCommand(player, Collections.singletonList(code));
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(codeManager).isVerificationRequired(player);
|
||||||
|
verify(codeManager).hasEmail(name);
|
||||||
|
verify(commonService).send(player, MessageKey.VERIFICATION_CODE_EMAIL_NEEDED);
|
||||||
|
verify(commonService).send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldDefineArgumentMismatchMessage() {
|
||||||
|
// given / when / then
|
||||||
|
assertThat(command.getArgumentsMismatchMessage(), equalTo(MessageKey.USAGE_VERIFICATION_CODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Player mockPlayerWithName(String name) {
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
given(player.getName()).willReturn(name);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package fr.xephi.authme.data;
|
||||||
|
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSourceResult;
|
||||||
|
import fr.xephi.authme.mail.EmailService;
|
||||||
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
|
import fr.xephi.authme.permission.PlayerPermission;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.only;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link VerificationCodeManager}.
|
||||||
|
*/
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class VerificationCodeManagerTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private EmailService emailService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PermissionsManager permissionsManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpBasicBehavior() {
|
||||||
|
given(emailService.hasAllInformation()).willReturn(true);
|
||||||
|
given(settings.getProperty(SecuritySettings.VERIFICATION_CODE_EXPIRATION_MINUTES)).willReturn(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRequireVerification() {
|
||||||
|
// given
|
||||||
|
String name1 = "ILoveTests";
|
||||||
|
Player player1 = mockPlayerWithName(name1);
|
||||||
|
given(dataSource.getEmail(name1)).willReturn(DataSourceResult.of("ilovetests@test.com"));
|
||||||
|
given(permissionsManager.hasPermission(player1, PlayerPermission.VERIFICATION_CODE)).willReturn(true);
|
||||||
|
String name2 = "StillLovingTests";
|
||||||
|
Player player2 = mockPlayerWithName(name2);
|
||||||
|
|
||||||
|
VerificationCodeManager codeManager = createCodeManager();
|
||||||
|
codeManager.verify(name2);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean test1 = codeManager.isVerificationRequired(player1);
|
||||||
|
boolean test2 = codeManager.isVerificationRequired(player2);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(test1, equalTo(true));
|
||||||
|
assertThat(test2, equalTo(false));
|
||||||
|
verify(dataSource, only()).getEmail(name1);
|
||||||
|
verify(permissionsManager, only()).hasPermission(player1, PlayerPermission.VERIFICATION_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotRequireVerificationIfEmailSettingsAreIncomplete() {
|
||||||
|
// given
|
||||||
|
given(emailService.hasAllInformation()).willReturn(false);
|
||||||
|
VerificationCodeManager codeManager = createCodeManager();
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = codeManager.isVerificationRequired(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(false));
|
||||||
|
verifyZeroInteractions(permissionsManager, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotRequireVerificationForMissingPermission() {
|
||||||
|
// given
|
||||||
|
Player player = mockPlayerWithName("ILoveTests");
|
||||||
|
given(permissionsManager.hasPermission(player, PlayerPermission.VERIFICATION_CODE)).willReturn(false);
|
||||||
|
VerificationCodeManager codeManager = createCodeManager();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = codeManager.isVerificationRequired(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(false));
|
||||||
|
verify(permissionsManager).hasPermission(player, PlayerPermission.VERIFICATION_CODE);
|
||||||
|
verifyZeroInteractions(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldGenerateCode() {
|
||||||
|
// given
|
||||||
|
String player = "ILoveTests";
|
||||||
|
String email = "ilovetests@test.com";
|
||||||
|
given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
|
||||||
|
VerificationCodeManager codeManager1 = createCodeManager();
|
||||||
|
VerificationCodeManager codeManager2 = createCodeManager();
|
||||||
|
codeManager2.codeExistOrGenerateNew(player);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean test1 = codeManager1.hasCode(player);
|
||||||
|
boolean test2 = codeManager2.hasCode(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(test1, equalTo(false));
|
||||||
|
assertThat(test2, equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldRequireCode() {
|
||||||
|
// given
|
||||||
|
String player = "ILoveTests";
|
||||||
|
String email = "ilovetests@test.com";
|
||||||
|
given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
|
||||||
|
VerificationCodeManager codeManager1 = createCodeManager();
|
||||||
|
VerificationCodeManager codeManager2 = createCodeManager();
|
||||||
|
codeManager2.codeExistOrGenerateNew(player);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean test1 = codeManager1.isCodeRequired(player);
|
||||||
|
boolean test2 = codeManager2.isCodeRequired(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(test1, equalTo(false));
|
||||||
|
assertThat(test2, equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldVerifyCode() {
|
||||||
|
// given
|
||||||
|
String player = "ILoveTests";
|
||||||
|
String code = "193458";
|
||||||
|
String email = "ilovetests@test.com";
|
||||||
|
given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
|
||||||
|
VerificationCodeManager codeManager1 = createCodeManager();
|
||||||
|
VerificationCodeManager codeManager2 = createCodeManager();
|
||||||
|
codeManager1.codeExistOrGenerateNew(player);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean test1 = codeManager1.checkCode(player, code);
|
||||||
|
boolean test2 = codeManager2.checkCode(player, code);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(test1, equalTo(false));
|
||||||
|
assertThat(test2, equalTo(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerificationCodeManager createCodeManager() {
|
||||||
|
return new VerificationCodeManager(settings, dataSource, emailService, permissionsManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Player mockPlayerWithName(String name) {
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
given(player.getName()).willReturn(name);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
}
|
@ -77,6 +77,24 @@ public class SettingsTest {
|
|||||||
assertThat(result, equalTo(emailMessage));
|
assertThat(result, equalTo(emailMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldLoadVerificationMessage() throws IOException {
|
||||||
|
// given
|
||||||
|
String emailMessage = "Please verify your identity with <recoverycode />.";
|
||||||
|
File emailFile = new File(testPluginFolder, "verification_code_email.html");
|
||||||
|
createFile(emailFile);
|
||||||
|
Files.write(emailFile.toPath(), emailMessage.getBytes());
|
||||||
|
|
||||||
|
PropertyResource resource = mock(PropertyResource.class);
|
||||||
|
Settings settings = new Settings(testPluginFolder, resource, null, CONFIG_DATA);
|
||||||
|
|
||||||
|
// when
|
||||||
|
String result = settings.getVerificationEmailMessage();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(emailMessage));
|
||||||
|
}
|
||||||
|
|
||||||
private static void createFile(File file) {
|
private static void createFile(File file) {
|
||||||
try {
|
try {
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
|
@ -61,6 +61,22 @@ public class RandomStringUtilsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldGenerateRandomNumberString() {
|
||||||
|
// given
|
||||||
|
int[] lengths = {0, 1, 18, 147, 1833};
|
||||||
|
Pattern badChars = Pattern.compile(".*[^0-9].*");
|
||||||
|
|
||||||
|
// when / then
|
||||||
|
for (int length : lengths) {
|
||||||
|
String result = RandomStringUtils.generateNum(length);
|
||||||
|
assertThat("Result '" + result + "' should have length " + length,
|
||||||
|
result.length(), equalTo(length));
|
||||||
|
assertThat("Result '" + result + "' should only have characters 0-9",
|
||||||
|
badChars.matcher(result).matches(), equalTo(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void shouldThrowForInvalidLength() {
|
public void shouldThrowForInvalidLength() {
|
||||||
// given/when
|
// given/when
|
||||||
|
Loading…
Reference in New Issue
Block a user